hdu_4897_Little Devil I(树链剖分)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4897

题意:有三种操作,1是在树上的两个节点之间的路径改变当前的颜色,2是改变树上有且只有一个端点在u,v之间的边的颜色,3是询问u,v之间黑色边的条数

题解:对于1,就是一般的树链剖分操作,对于2,我们知道树剖把树分成了重链和轻链,我们要充分利用这个结构才能降低时间复杂度,这里我们建立两个线段树来保存重链的sum和对每一个点的标记vis,第二个线段树表示如果这个点标记为1,那么以这个点周围的边都会改变,然后对于重链上的点,我们就直接在sum上操作,遇到轻链上的点,就在vis上标记,最后查询的时候先找sum上真实改变的边,然后当 当前的top跳到另一个top时,此时要查询vis上和sum上异或的值,最后全部加起来就是答案,要好好的想一想才能理解

  1 #include<cstdio>
  2 #define F(i,a,b) for(int i=a;i<=b;i++)
  3 
  4 const int N=1e5+7;
  5 int t,n,op,q,x,y,g[N],nxt[N<<1],v[N<<1],ed;
  6 inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
  7 //--------------树链剖分---------------
  8 int dep[N],sz[N],hs[N],top[N],fa[N],tid[N],idx;
  9 void dfs1(int u,int pre){
 10     fa[u]=pre,sz[u]=1,dep[u]=dep[pre]+1,hs[u]=0;
 11     for(int i=g[u];~i;i=nxt[i])if(v[i]!=pre)
 12     dfs1(v[i],u),sz[u]+=sz[v[i]],hs[u]=sz[v[i]]>sz[hs[u]]?v[i]:hs[u];
 13 }
 14 void dfs2(int u,int tp){
 15     tid[u]=++idx,top[u]=tp;
 16     if(hs[u])dfs2(hs[u],tp);
 17     for(int i=g[u];~i;i=nxt[i])
 18     if(v[i]!=fa[u]&&v[i]!=hs[u])dfs2(v[i],v[i]);
 19 }
 20 //--------------线段树------------------
 21 #define root 1,n,1
 22 #define ls l,m,rt<<1
 23 #define rs m+1,r,rt<<1|1
 24 int sum[N<<2],vis[N<<2],ly1[N<<2];
 25 
 26 inline void sink(int rt,int tot){ly1[rt]^=1,sum[rt]=tot-sum[rt];}
 27 
 28 inline void pd(int op,int l,int r,int rt){
 29     if(op==1){
 30         if(ly1[rt]){
 31         int m=(l+r)>>1;
 32         sink(rt<<1,m-l+1),sink(rt<<1|1,r-m);
 33         ly1[rt]=0;
 34         }
 35     }else if(vis[rt])vis[rt<<1]^=1,vis[rt<<1|1]^=1,vis[rt]=0;
 36 }
 37 inline void up_p(int L,int R,int l,int r,int rt){
 38     if(L<=l&&r<=R){
 39         sink(rt,r+1-l);
 40         return;
 41     }
 42     pd(1,l,r,rt);
 43     int m=(l+r)>>1;
 44     if(L<=m)up_p(L,R,ls);
 45     if(R>m)up_p(L,R,rs);
 46     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
 47 }
 48 inline int q_p(int L,int R,int l,int r,int rt){
 49     if(L<=l&&r<=R)return sum[rt];
 50     int m=(l+r)>>1,ret=0;
 51     pd(1,l,r,rt);
 52     if(L<=m)ret+=q_p(L,R,ls);
 53     if(m<R)ret+=q_p(L,R,rs);
 54     return ret;
 55 }
 56 inline void up_v(int L,int R,int l,int r,int rt){
 57     if(L<=l&&r<=R){vis[rt]^=1;return;}
 58     pd(2,l,r,rt);
 59     int m=(l+r)>>1;
 60     if(L<=m)up_v(L,R,ls);
 61     if(R>m)up_v(L,R,rs);
 62 }
 63 inline int q_v(int x,int l,int r,int rt){
 64     if(l==r)return vis[rt];
 65     pd(2,l,r,rt);
 66     int m=(l+r)>>1,ret=0;
 67     if(x<=m)ret^=q_v(x,ls);
 68     else ret^=q_v(x,rs);
 69     return ret;
 70 }
 71 //--------------------------------------
 72 inline int ask(int x,int y){
 73     int ans=0;
 74     while(top[x]!=top[y]){
 75         if(dep[top[x]]<dep[top[y]])x^=y,y^=x,x^=y;
 76         if(x!=top[x])ans+=q_p(tid[top[x]]+1,tid[x],root);
 77         ans+=q_v(tid[fa[top[x]]],root)^q_p(tid[top[x]],tid[top[x]],root);
 78         x=fa[top[x]];
 79     }    
 80     if(x==y)return ans;
 81     if(dep[x]>dep[y])x^=y,y^=x,x^=y;
 82     ans+=q_p(tid[x]+1,tid[y],root);
 83     return ans;
 84 }
 85 inline void up(int op,int x,int y){
 86     if(op==1){
 87         while(top[x]!=top[y]){
 88             if(dep[top[x]]<dep[top[y]])x^=y,y^=x,x^=y;
 89             up_p(tid[top[x]],tid[x],root),x=fa[top[x]];
 90         }
 91         if(x!=y){
 92             if(dep[x]>dep[y])x^=y,y^=x,x^=y;
 93             up_p(tid[x]+1,tid[y],root);
 94         }
 95     }else{
 96         while(top[x]!=top[y]){
 97             if(dep[top[x]]<dep[top[y]])x^=y,y^=x,x^=y;
 98             up_v(tid[top[x]],tid[x],root);
 99             up_p(tid[top[x]],tid[top[x]],root);
100             if(hs[x])up_p(tid[x]+1,tid[hs[x]],root);
101             x=fa[top[x]];
102         }
103             if(dep[x]>dep[y])x^=y,y^=x,x^=y;
104             up_v(tid[x],tid[y],root);
105             up_p(tid[x],tid[x],root);
106             if(hs[y])up_p(tid[y]+1,tid[hs[y]],root);
107     }
108 }
109 
110 int main(){
111     scanf("%d",&t);
112     while(t--){
113         scanf("%d",&n);
114         F(i,0,n)g[i]=-1;ed=0;
115         F(i,0,n<<2)sum[i]=0,vis[i]=0,ly1[i]=0;
116         F(i,1,n-1)scanf("%d%d",&x,&y),adg(x,y),adg(y,x);
117         dfs1(1,0),idx=0,dfs2(1,1),scanf("%d",&q);
118         while(q--){
119             scanf("%d%d%d",&op,&x,&y);
120             if(op<3)up(op,x,y);else printf("%d\n",ask(x,y));    
121         }
122     }
123     return 0;
124 }
View Code

 

posted @ 2016-07-01 16:53  bin_gege  阅读(204)  评论(0编辑  收藏  举报