A1505. 树(张闻涛)
时间限制:1.0s   内存限制:512.0MB   
总提交次数:196   AC次数:65   平均分:58.62
 
将本题分享到:
      
试题来源
  2013中国国家集训队第二次作业
问题描述
  给定一棵N个节点的树,每个点有一个权值,有M个询问(a,b,c)若a 为1,回答b到c路径上的最小权值,若a为2,回答b到c路径上的最大权值,若a为3,回答b到c路径上的所有权值的中位数,k个数的中位数定义为从0到k-1编号从小到大排序后k/2号的那个数。
输入格式
  第一行两个整数N,M
  第二行N个整数,v[1]~v[n],代表每个节点的权值。
  接下来N-1行每行两个整数x,y代表x和y有一条边
  最后M行每行三个整数a,b,c,表示一组询问。
输出格式
  共M行,每行一个整数,代表询问的答案。
样例输入
5 3
1 3 2 4 5
1 2
2 4
4 3
4 5
1 1 5
2 1 3
3 1 5
样例输出
1
4
4
数据规模和约定
  共20个数据
  数据1~3 N,M<=1000
  数据4~6 N,M<=5000
  数据7~10 N,M<=10000
  数据11~18 N,M<=30000
  数据19~20 N,M<=100000
 
 
题解:
倍增LCA+可持久化线段树+DFS序
 
直接把可持久化线段树建到DFS序上即可。
每个点由其 父亲结点 为基础建立即可。
设询问 u -> v 路径,路径上点数为k个。
然后若a=1,输出链上排第一小的。
a=2,输出链上排第k小的。
a=3,输出链上排第k/2+1小的。
 #include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
struct node
{
int begin,end,next;
}edge[MAXN*];
struct NODE
{
int left,right;
}tree[MAXN*];
int cnt,Head[MAXN],SIZE,deep[MAXN],P[MAXN][],tot,root[MAXN],n,sum[MAXN*],val[MAXN],cc[MAXN],pos[MAXN],value[MAXN];
bool vis[MAXN];
void addedge(int bb,int ee)
{
edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].next=Head[bb];Head[bb]=cnt;
}
void addedge1(int bb,int ee)
{
addedge(bb,ee);addedge(ee,bb);
}
int read()
{
int s=,fh=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')fh=-;ch=getchar();}
while(ch>=''&&ch<=''){s=s*+(ch-'');ch=getchar();}
return s*fh;
}
void dfs(int u)
{
int i,v;
vis[u]=true;
SIZE++;pos[u]=SIZE;value[SIZE]=u;
for(i=Head[u];i!=-;i=edge[i].next)
{
v=edge[i].end;
if(vis[v]==false)
{
deep[v]=deep[u]+;
P[v][]=u;
dfs(v);
}
}
}
void Ycl()
{
int i,j;
for(j=;(<<j)<=n;j++)
{
for(i=;i<=n;i++)
{
if(P[i][j-]!=-)P[i][j]=P[P[i][j-]][j-];
}
}
}
int LCA(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
int i,j;
for(i=;(<<i)<=deep[x];i++);i--;
for(j=i;j>=;j--)if(deep[x]-(<<j)>=deep[y])x=P[x][j];
if(x==y)return x;
for(j=i;j>=;j--)
{
if(P[x][j]!=-&&P[x][j]!=P[y][j])
{
x=P[x][j];
y=P[y][j];
}
}
return P[x][];
}
void Build(int x,int &y,int l,int r,int B)
{
y=++SIZE;
sum[y]=sum[x]+;
if(l==r)return;
tree[y].left=tree[x].left;tree[y].right=tree[x].right;
int mid=(l+r)/;
if(B<=mid)Build(tree[x].left,tree[y].left,l,mid,B);
else Build(tree[x].right,tree[y].right,mid+,r,B);
}
int Query(int l,int r,int A,int B,int C,int D,int Q)
{
if(l==r)return l;
int mid,delta=sum[tree[A].left]+sum[tree[B].left]-sum[tree[C].left]-sum[tree[D].left];
mid=(l+r)/;
if(Q<=delta)return Query(l,mid,tree[A].left,tree[B].left,tree[C].left,tree[D].left,Q);
else return Query(mid+,r,tree[A].right,tree[B].right,tree[C].right,tree[D].right,Q-delta);
}
int query(int u,int v,int lca,int k)
{
int A=pos[u],B=pos[v],C=pos[lca],D=pos[P[lca][]];
return Query(,tot,root[A],root[B],root[C],root[D],k);
}
int main()
{
int m,i,wz,s1,s2,s3,lca,k,bb,ee;
n=read();m=read();
for(i=;i<=n;i++)val[i]=read(),cc[i]=val[i];
sort(cc+,cc+n+);
tot=unique(cc+,cc+n+)-(cc+);
memset(Head,-,sizeof(Head));cnt=;
for(i=;i<n;i++){bb=read();ee=read();addedge1(bb,ee);}
memset(P,-,sizeof(P));
SIZE=;
dfs();Ycl();
SIZE=;
for(i=;i<=n;i++)//按树上顺序插入.
{
k=value[i];
wz=lower_bound(cc+,cc+tot+,val[k])-cc;
Build(root[pos[P[k][]]],root[i],,tot,wz);
}
SIZE=;
for(i=;i<=m;i++)
{
s1=read();s2=read();s3=read();
if(s1==){lca=LCA(s2,s3);printf("%d\n",cc[query(s2,s3,lca,)]);}
else if(s1==){lca=LCA(s2,s3);k=deep[s2]+deep[s3]-*deep[lca]+;printf("%d\n",cc[query(s2,s3,lca,k)]);}
else {lca=LCA(s2,s3);k=(deep[s2]+deep[s3]-*deep[lca]+)/;printf("%d\n",cc[query(s2,s3,lca,k)]);}
}
fclose(stdin);
fclose(stdout);
return ;
}

Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序的更多相关文章

  1. 【bzoj2653】middle 可持久化线段树区间合并

    题目描述 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[ ...

  2. BZOJ - 2588 Spoj 10628. Count on a tree (可持久化线段树+LCA/树链剖分)

    题目链接 第一种方法,dfs序上建可持久化线段树,然后询问的时候把两点之间的所有树链扒出来做差. #include<bits/stdc++.h> using namespace std; ...

  3. [HNOI2016]树(可持久化线段树+树上倍增)

    [HNOI2016]树(可持久化线段树+树上倍增) 题面 给出一棵n个点的模板树和大树,根为1,初始的时候大树和模板树相同.接下来操作m次,每次从模板树里取出一棵子树,把它作为新树里节点y的儿子.操作 ...

  4. BZOJ4771七彩树——可持久化线段树+set+树链的并+LCA

    给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节 点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义dept ...

  5. 51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径

    51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径 题面 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即 ...

  6. BZOJ 2588: Spoj 10628. Count on a tree-可持久化线段树+LCA(点权)(树上的操作) 无语(为什么我的LCA的板子不对)

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 9280  Solved: 2421 ...

  7. [IOI2018]狼人——kruskal重构树+可持久化线段树

    题目链接: IOI2018werewolf 题目大意:给出一张$n$个点$m$条边的无向图,点和边可重复经过,一个狼人初始为人形,有$q$次询问,每次询问要求人形态只能处于编号不小于$L$的点,狼形态 ...

  8. BZOJ - 3123 森林 (可持久化线段树+启发式合并)

    题目链接 先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树.当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组.树的结点数可以用并查集来维护 ...

  9. SPOJ-COT-Count on a tree(树上路径第K小,可持久化线段树)

    题意: 求树上A,B两点路径上第K小的数 分析: 同样是可持久化线段树,只是这一次我们用它来维护树上的信息. 我们之前已经知道,可持久化线段树实际上是维护的一个前缀和,而前缀和不一定要出现在一个线性表 ...

随机推荐

  1. xml 嵌入式资源

    使用Ibatis总是说未能加载相应的sqlmap.xml,原来是 xml以内容方式,而不是嵌入式方式载入Dll中

  2. 淘宝技术发展(Java时代:脱胎换骨)

    我的师父黄裳@岳旭强曾经说过,“好的架构图充满美感”,一个架构好不好,从审美的角度就能看得出来.后来我看了很多系统的架构,发现这个言论基本成立.那么反观淘宝前面的两个版本的架构,你看哪个比较美? 显然 ...

  3. 移植strace调试工具到arm平台

    strace工具是一个非常强大的工具,是调试程序的好工具.要移植到arm平台,就需要使用交叉编译工具编译生成静态链接的可执行文件.具体步骤如下:1.下载 strace-4.5.16     移植str ...

  4. Layui文件上传样式在ng-dialog不显示的问题处理

    1.项目业务改动,在一个弹窗页面加图片上传. 2.页面使用angular框架,图片上传使用layui的文件上传组件. js: layui.upload({ url: '/test/upload.jso ...

  5. IOS开发中多线程的使用

    一.创建多线程的五种方式 1.开启线程的方法一 NSThread * thread=[[NSThread alloc] initWithTarget:self selector:@selector(_ ...

  6. Hibernate的核心接口

    Hibernate5个核心接口 所有Hibernate应用中都会访问Hibernate的5个核心接口 Configuration接口:配置Hibernate,根启动Hibernate,创建Sessio ...

  7. React路由 + 绝对路径引用

    路由: 哈希路由(在url地址后加   #name) // 实现页面监听 window.onhashchange = function(){ console.log(‘hash:’,window.lo ...

  8. c++学习笔记(七)- lambda表达式 迭代器 算法

    关于lambda表达式: 刷题的时候遇到一句代码不懂: char ch = *it;auto it2 = find_if(it, b.end(), [ch](char x){ return x != ...

  9. hdu 1057 A + B Again

    A + B Again Problem Description There must be many A + B problems in our HDOJ , now a new one is com ...

  10. python中关于if-else使用性能的一点感悟

    今天做leetcode第7题关于数字倒序的问题,分别使用如下程序:(72ms) class Solution: def reverse(self, x): """ :ty ...