QTREE - Query on a tree
题目链接:http://www.spoj.com/problems/QTREE/
参考博客:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html
树链剖分入门题
代码如下(附注解):
#include <cstdio> #include <cstring> #include <iostream> #define lson (x<<1) #define rson ((x<<1)|1) #define mid ((l+r)>>1) #define N 10010 using namespace std; struct Edge{ int to,next; }e[N<<]; int T,n,tot,oo,root; ],tree[N<<];//头结点,inpotData,线段树 int fa[N],siz[N],dep[N],son[N];//父亲,包含该节点的子树的结点数,深度,重链上的儿子 int top[N],p[N];//当前节点所在重链的顶端结点,当前节点与其父亲的连边在线段树中的位置 ]; void addEdge(int u,int v){//用头接法链表存当前节点的各个儿子 e[++oo].to=v; e[oo].next=head[u]; head[u]=oo; } void fristDFS(int v){//第一次dfs求siz,son,dep,fa siz[v]=,son[v]=; ;i=e[i].next){ int u=e[i].to; if(u!=fa[v]){ fa[u]=v; dep[u]=dep[v]+; fristDFS(u); if(siz[u]>siz[son[v]])son[v]=u; siz[v]+=siz[u]; } } } void secondDFS(int v,int tp){//第二次dfs求top,p p[v]=++tot,top[v]=tp; )secondDFS(son[v],top[v]); ;i=e[i].next){ int u=e[i].to; if(u!=fa[v]&&u!=son[v])secondDFS(u,u); } } void push_up(int x){ tree[x]=max(tree[lson],tree[rson]); } void updata(int x,int l,int r,int p,int v){//建线段树 if(l==r){ tree[x]=v; return; } if(p<=mid)updata(lson,l,mid,p,v); ,r,p,v); push_up(x); } void init(){ memset(siz,,sizeof(siz)); memset(head,,sizeof(head)); scanf("%d",&n); root=(n+)/;//任意取一个root oo=tot=fa[root]=dep[root]=; ;i<n;++i){ ;j<;++j)scanf("%d",&a[i][j]); addEdge(a[i][],a[i][]); addEdge(a[i][],a[i][]); } fristDFS(root); secondDFS(root,root); ;i<n;++i){ ]]>dep[a[i][]])swap(a[i][],a[i][]); //将远离root的结点放在d[i][1] updata(,,tot,p[a[i][]],a[i][]); } } int query(int x,int l,int r,int a,int b){ if(a<=l&&r<=b)return tree[x]; ; if(a<=mid)tmp=max(tmp,query(lson,l,mid,a,b)); ,r,a,b)); return tmp; } int find(int x,int y){ ; while(f1!=f2){//若x,y不在同一条重链上 if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y); //取深度大的点,f1为该重边的顶端结点,va为该结点 //在线段树中[f1,va]一定为一个连续的区间 tmp=max(tmp,query(,,tot,p[f1],p[x])); x=fa[f1];f1=top[x]; } if(x==y)return tmp; if(dep[y]<dep[x])swap(x,y); ,,tot,p[son[x]],p[y]));//不包含x与其父亲构成的边 } void solve(){ int x,y; ]!='D';scanf("%s",s)){ scanf("%d%d",&x,&y); ]=='Q')printf("%d\n",find(x,y)); ]==,,tot,p[a[x][]],y); } } int main(void){ for(scanf("%d",&T);T;T--){ init(); solve(); } }