首页 > 代码库 > QTREE - Query on a tree

QTREE - Query on a tree

QTREE - Query on a tree

题目链接:http://www.spoj.com/problems/QTREE/

参考博客:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

树链剖分入门题

代码如下(附注解):

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #define lson (x<<1)
  5 #define rson ((x<<1)|1)
  6 #define mid ((l+r)>>1)
  7 #define N 10010
  8 using namespace std;
  9 struct     Edge{
 10     int to,next;
 11 }e[N<<1];
 12 int T,n,tot,oo,root;
 13 int head[N],a[N][3],tree[N<<2];//头结点,inpotData,线段树
 14 int fa[N],siz[N],dep[N],son[N];//父亲,包含该节点的子树的结点数,深度,重链上的儿子
 15 int top[N],p[N];//当前节点所在重链的顶端结点,当前节点与其父亲的连边在线段树中的位置
 16 char s[10];
 17 void addEdge(int u,int v){//用头接法链表存当前节点的各个儿子
 18     e[++oo].to=v;
 19     e[oo].next=head[u];
 20     head[u]=oo;
 21 }
 22 void fristDFS(int v){//第一次dfs求siz,son,dep,fa
 23     siz[v]=1,son[v]=0;
 24     for(int i=head[v];i!=0;i=e[i].next){
 25         int u=e[i].to;
 26         if(u!=fa[v]){
 27             fa[u]=v;
 28             dep[u]=dep[v]+1;
 29             fristDFS(u);
 30             if(siz[u]>siz[son[v]])son[v]=u;
 31             siz[v]+=siz[u];
 32         }
 33     }
 34 }
 35 void secondDFS(int v,int tp){//第二次dfs求top,p
 36     p[v]=++tot,top[v]=tp;
 37     if(son[v]!=0)secondDFS(son[v],top[v]);
 38     for(int i=head[v];i!=0;i=e[i].next){
 39         int u=e[i].to;
 40         if(u!=fa[v]&&u!=son[v])secondDFS(u,u);
 41     }
 42 }
 43 void push_up(int x){
 44     tree[x]=max(tree[lson],tree[rson]);
 45 }
 46 void updata(int x,int l,int r,int p,int v){//建线段树
 47     if(l==r){
 48         tree[x]=v;
 49         return;
 50     }
 51     if(p<=mid)updata(lson,l,mid,p,v);
 52     else updata(rson,mid+1,r,p,v);
 53     push_up(x);
 54 }
 55 void init(){
 56     memset(siz,0,sizeof(siz));
 57     memset(head,0,sizeof(head));
 58     scanf("%d",&n);
 59     root=(n+1)/2;//任意取一个root
 60     oo=tot=fa[root]=dep[root]=0;
 61     for(int i=1;i<n;++i){
 62         for(int j=0;j<3;++j)scanf("%d",&a[i][j]);
 63         addEdge(a[i][0],a[i][1]);
 64         addEdge(a[i][1],a[i][0]);
 65     }
 66     fristDFS(root);
 67     secondDFS(root,root);
 68     for(int i=1;i<n;++i){
 69         if(dep[a[i][0]]>dep[a[i][1]])swap(a[i][0],a[i][1]);
 70         //将远离root的结点放在d[i][1]
 71         updata(1,1,tot,p[a[i][1]],a[i][2]);
 72     }
 73 }
 74 int query(int x,int l,int r,int a,int b){
 75     if(a<=l&&r<=b)return tree[x];
 76     int tmp=0;
 77     if(a<=mid)tmp=max(tmp,query(lson,l,mid,a,b));
 78     if(b>mid)tmp=max(tmp,query(rson,mid+1,r,a,b));
 79     return tmp;
 80 }
 81 int find(int x,int y){
 82     int f1=top[x],f2=top[y],tmp=0;
 83     while(f1!=f2){//若x,y不在同一条重链上
 84         if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y);
 85         //取深度大的点,f1为该重边的顶端结点,va为该结点
 86         //在线段树中[f1,va]一定为一个连续的区间
 87         tmp=max(tmp,query(1,1,tot,p[f1],p[x]));
 88         x=fa[f1];f1=top[x];
 89     }
 90     if(x==y)return tmp;
 91     if(dep[y]<dep[x])swap(x,y);
 92     return max(tmp,query(1,1,tot,p[son[x]],p[y]));//不包含x与其父亲构成的边
 93 }
 94 void solve(){
 95     int x,y;
 96     for(scanf("%s",s);s[0]!=D;scanf("%s",s)){
 97         scanf("%d%d",&x,&y);
 98         if(s[0]==Q)printf("%d\n",find(x,y));
 99         else if(s[0]==C)updata(1,1,tot,p[a[x][1]],y);
100     }
101 }
102 int main(void){
103     for(scanf("%d",&T);T;T--){
104         init();
105         solve();
106     }
107 }

 

QTREE - Query on a tree