Codeforces 343D Water Tree(DFS序 + 线段树)

题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1、把某结点以及其各个祖先值设为0、询问某结点的值。

对于第一个操作就是经典的DFS序+线段树了。而对于第二个操作,考虑再维护一个域表示各个结点为根的子树是否有进行第二个操作,如果有那么该结点应该就要是0;而在进行第一个操作前,看一下子树是否有进行第二个操作,如果有就整个标记成没有并把标记上传,让该结点的父亲结点标记成进行了第二个操作。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 #define MAXN 555555
  6 
  7 struct Edge{
  8     int v,next;
  9 }edge[MAXN<<1];
 10 int NE,head[MAXN];
 11 void addEdge(int u,int v){
 12     edge[NE].v=v; edge[NE].next=head[u];
 13     head[u]=NE++;
 14 }
 15 
 16 int l[MAXN],r[MAXN],par[MAXN],dfn;
 17 void dfs(int u,int fa){
 18     l[u]=++dfn;
 19     for(int i=head[u]; i!=-1; i=edge[i].next){
 20         int v=edge[i].v;
 21         if(v==fa) continue;
 22         par[v]=u;
 23         dfs(v,u);
 24     }
 25     r[u]=dfn;
 26 }
 27 
 28 int x,y,z,N;
 29 bool tree[MAXN<<2],down[MAXN<<2],up[MAXN<<2];
 30 void updateUp(int i,int j,int k){
 31     if(x<=i && j<=y){
 32         up[k]=z;
 33         return;
 34     }
 35     if(up[k]==0){
 36         up[k<<1]=0;
 37         up[k<<1|1]=0;
 38     }
 39     int mid=i+j>>1;
 40     if(x<=mid) updateUp(i,mid,k<<1);
 41     if(y>mid) updateUp(mid+1,j,k<<1|1);
 42     up[k]=up[k<<1]|up[k<<1|1];
 43 }
 44 bool queryUp(int i,int j,int k){
 45     if(x<=i && j<=y){
 46         return up[k];
 47     }
 48     if(up[k]==0){
 49         up[k<<1]=0;
 50         up[k<<1|1]=0;
 51     }
 52     int mid=i+j>>1; bool res=0;
 53     if(x<=mid) res|=queryUp(i,mid,k<<1);
 54     if(y>mid) res|=queryUp(mid+1,j,k<<1|1);
 55     return res;
 56 }
 57 
 58 void update(int i,int j,int k){
 59     if(x<=i && j<=y){
 60         tree[k]=z;
 61         down[k]=z;
 62         return;
 63     }
 64     if(down[k]==1){
 65         tree[k<<1]=1;
 66         tree[k<<1|1]=1;
 67         down[k<<1]=1;
 68         down[k<<1|1]=1;
 69         down[k]=0;
 70     }
 71     int mid=i+j>>1;
 72     if(x<=mid) update(i,mid,k<<1);
 73     if(y>mid) update(mid+1,j,k<<1|1);
 74 }
 75 bool query(int i,int j,int k){
 76     if(i==j){
 77         return tree[k];
 78     }
 79     if(down[k]==1){
 80         tree[k<<1]=1;
 81         tree[k<<1|1]=1;
 82         down[k<<1]=1;
 83         down[k<<1|1]=1;
 84         down[k]=0;
 85     }
 86     int mid=i+j>>1;
 87     if(x<=mid) return query(i,mid,k<<1);
 88     else query(mid+1,j,k<<1|1);
 89 }
 90 
 91 int main(){
 92     int n,q,a,b;
 93     scanf("%d",&n);
 94     memset(head,-1,sizeof(head));
 95     for(int i=1; i<n; ++i){
 96         scanf("%d%d",&a,&b);
 97         addEdge(a,b);
 98         addEdge(b,a);
 99     }
100 
101     for(N=1; N<n; N<<=1);
102     dfs(1,1);
103 
104     scanf("%d",&q);
105     while(q--){
106         scanf("%d%d",&a,&b);
107         if(a==1){
108             x=l[b]; y=r[b];
109             if(queryUp(1,N,1)){
110                 z=0;
111                 updateUp(1,N,1);
112                 if(b!=1){
113                     x=l[par[b]]; y=l[par[b]]; z=1;
114                     updateUp(1,N,1);
115                 }
116             }
117             x=l[b]; y=r[b]; z=1;
118             update(1,N,1);
119         }else if(a==2){
120             x=l[b]; y=l[b]; z=1;
121             updateUp(1,N,1);
122         }else if(a==3){
123             x=l[b]; y=r[b];
124             if(queryUp(1,N,1)){
125                 puts("0");
126             }else{
127                 x=l[b]; y=l[b];
128                 printf("%d\n",query(1,N,1));
129             }
130         }
131     }
132     return 0;
133 }

 

posted @ 2016-07-18 15:13  WABoss  阅读(260)  评论(0编辑  收藏  举报