hdu4897 Little Devil I

题意:给定一棵树,初始边权为零,对其进行以下操作:

1. 把树上a到b的路径上的边权:0变为1,1变为0。

2. 与树上a到b的路径相邻的边(只有一个公共点),把它们的边权:0变为1,1变为0。

3. 查询a到b的路径上的边权和。

思路:

操作1用普通的重链剖分就可以解决。

对于操作2,可以看出,在每次从重链的底部跳到重链顶端的过程中,除重链底部和重链顶端可能连一条相邻的(不是底部到顶端路径上的)重边外,其余的相邻边都是轻边。所以我们可以再开一个线段树记录与树上的每个点是否被标记,如果被标记,说明与它相邻的轻边也被标记。

对于操作3,路径上的所有重边可以通过第一个线段树(存边权和那个)解决,路径上的轻边则还取决于:它的两个端点是否被标记。

代码:

 

  1 #include<bits/stdc++.h>
  2 #define lson l,mid,rt<<1
  3 #define rson mid+1,r,rt<<1|1
  4 using namespace std;
  5 const int N=1e5+10;
  6 const int M=2e5+10;
  7 const int inf=0x3f3f3f3f;
  8 
  9 int head[N],to[M],nxt[M];
 10 int tot;
 11 int dep[N],fa[N],siz[N],son[N];
 12 int top[N],id[N];
 13 int cnt;
 14 int n;
 15 int sum[N<<2],mark[N<<2],tag1[N<<2],tag2[N<<2];
 16 
 17 inline void add(int u,int v){
 18     to[++tot]=v,nxt[tot]=head[u],head[u]=tot;
 19 }
 20 
 21 void dfs1(int u,int f){
 22     dep[u]=dep[f]+1;
 23     fa[u]=f;
 24     siz[u]=1;
 25     son[u]=0;
 26     int maxs=-1;
 27     for(int i=head[u];i;i=nxt[i]){
 28         int v=to[i];
 29         if(v==f) continue;
 30         dfs1(v,u);
 31         siz[u]+=siz[v];
 32         if(siz[v]>maxs) maxs=siz[v],son[u]=v;
 33     }
 34 }
 35 
 36 void dfs2(int u,int topf){
 37     id[u]=++cnt;
 38     top[u]=topf;
 39     if(!son[u]) return;
 40     dfs2(son[u],topf);
 41     for(int i=head[u];i;i=nxt[i]){
 42         int v=to[i];
 43         if(v==fa[u]||v==son[u]) continue;
 44         dfs2(v,v);
 45     }
 46 }
 47 
 48 void build(int l,int r,int rt){
 49     sum[rt]=mark[rt]=tag1[rt]=tag2[rt]=0;
 50     if(l==r) return;
 51     int mid=(l+r)>>1;
 52     build(lson);
 53     build(rson);
 54 }
 55 
 56 inline void push_up(int rt){
 57     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
 58 }
 59 
 60 void push_down1(int rt,int m){
 61     if(tag1[rt]){
 62         sum[rt<<1]=m-(m>>1)-sum[rt<<1];
 63         tag1[rt<<1]^=1;
 64         sum[rt<<1|1]=(m>>1)-sum[rt<<1|1];
 65         tag1[rt<<1|1]^=1;
 66         tag1[rt]=0;
 67     }
 68 }
 69 
 70 void update1(int x,int y,int l,int r,int rt){
 71     if(x<=l&&y>=r){
 72         sum[rt]=(r-l+1)-sum[rt];
 73         tag1[rt]^=1;
 74         return;
 75     }
 76     push_down1(rt,r-l+1);
 77     int mid=(l+r)>>1;
 78     if(x<=mid) update1(x,y,lson);
 79     if(y>mid) update1(x,y,rson);
 80     push_up(rt); 
 81 }
 82 
 83 int query1(int x,int y,int l,int r,int rt){
 84     if(x<=l&&y>=r) return sum[rt];
 85     push_down1(rt,r-l+1);
 86     int mid=(l+r)>>1;
 87     int ans=0;
 88     if(x<=mid) ans+=query1(x,y,lson);
 89     if(y>mid) ans+=query1(x,y,rson);
 90     return ans;
 91 }
 92 
 93 void push_down2(int rt){
 94     if(tag2[rt]){
 95         mark[rt<<1]^=1;
 96         mark[rt<<1|1]^=1;
 97         tag2[rt<<1]^=1;
 98         tag2[rt<<1|1]^=1;
 99         tag2[rt]=0;
100     }
101 }
102 
103 void update2(int x,int y,int l,int r,int rt){
104     if(x<=l&&y>=r){
105         mark[rt]^=1;
106         tag2[rt]^=1;
107         return;
108     }
109     push_down2(rt);
110     int mid=(l+r)>>1;
111     if(x<=mid) update2(x,y,lson);
112     if(y>mid) update2(x,y,rson);
113 }
114 
115 int query2(int x,int l,int r,int rt){
116     if(l==r) return mark[rt];
117     push_down2(rt);
118     int mid=(l+r)>>1;
119     if(x<=mid) return query2(x,lson);
120     return query2(x,rson);
121 }
122 
123 void uprange1(int x,int y){
124     while(top[x]!=top[y]){
125         if(dep[top[x]]<dep[top[y]]) swap(x,y);
126         update1(id[top[x]],id[x],1,n,1);
127         x=fa[top[x]];
128     }
129     if(x==y) return;
130     if(dep[x]>dep[y]) swap(x,y);
131     update1(id[x]+1,id[y],1,n,1);
132 }
133 
134 void uprange2(int x,int y){
135     while(top[x]!=top[y]){
136         if(dep[top[x]]<dep[top[y]]) swap(x,y);
137         update2(id[top[x]],id[x],1,n,1);
138         if(son[x]) update1(id[son[x]],id[son[x]],1,n,1);
139         x=fa[top[x]];
140     }
141     if(dep[x]>dep[y]) swap(x,y);
142     if(son[y]) update1(id[son[y]],id[son[y]],1,n,1);
143     if(son[fa[x]]==x) update1(id[x],id[x],1,n,1);
144     update2(id[x],id[y],1,n,1);
145 }
146 
147 int qrange(int x,int y){
148     int ans=0;
149     while(top[x]!=top[y]){
150         if(dep[top[x]]<dep[top[y]]) swap(x,y);
151         if(x!=top[x])
152             ans+=query1(id[top[x]]+1,id[x],1,n,1);
153         ans+=query1(id[top[x]],id[top[x]],1,n,1)^query2(id[fa[top[x]]],1,n,1)^query2(id[top[x]],1,n,1);
154         x=fa[top[x]];
155     }
156     if(x==y) return ans;
157     if(dep[x]>dep[y]) swap(x,y);
158     ans+=query1(id[x]+1,id[y],1,n,1);    
159     return ans;
160 }
161 
162 int main()
163 {
164     int T;
165     scanf("%d",&T);
166     while(T--){
167         tot=cnt=0;
168         memset(head,0,sizeof(head));
169         scanf("%d",&n);
170         for(int i=1;i<n;i++){
171             int u,v;
172             scanf("%d%d",&u,&v);
173             add(u,v);
174             add(v,u);
175         }
176         dfs1(1,0); dfs2(1,1);
177         build(1,n,1);
178         int q;
179         scanf("%d",&q);
180         while(q--){
181             int t,x,y;
182             scanf("%d%d%d",&t,&x,&y);
183             if(t==1) uprange1(x,y);
184             else if(t==2) uprange2(x,y);
185             else printf("%d\n",qrange(x,y));
186         }
187     }
188     return 0;
189 }

 

posted @ 2020-08-16 21:33  --HY--  阅读(200)  评论(0编辑  收藏  举报