マッドサイエンティストマイクはで構成されてい根ざしツリー、建設した n個の 頂点を。各頂点は、空または水で満たされたいずれかであることができるリザーバです。
ツリーの頂点が1から番号付けされている N個の 各頂点の頂点1でルートと、その子のリザーバは、この頂点のリザーバの下に配置され、頂点を介してパイプで子供のそれぞれに接続されていますその水が下方に流れることができます。
マイクは、ツリーで、次の操作をしたいです:
- 頂点塗りつぶし Vを 水で。そして、 V とそのすべての子が水で満たされています。
- 空の頂点 V。そして、 V とそのすべての祖先が空にされています。
- 頂点かどうかを決定します vは 、現時点では水で満たされています。
マイクは、すでに彼は順番に実行したい操作の完全なリストをまとめました。木を使って実験する前に、マイクは、シミュレーションにより、リストを実行することを決めました。マイクは結果が、彼はすべての操作を実行した後に取得するかを決定に役立ちます。
入力の最初の行は、整数含ま N (1≤ nは ツリーの頂点の数を- 500000≤)。以下の各 N - 1行は、2つのスペースで区切られた数字含ま のI、 B I (1≤ I、 bはiは ≤ N、 I ≠ B I) -木の縁。
次の行は、数字含ま Q (1つの≤ Q 実行する動作の数- 500000≤)を。以下の各 Qの 行は、二つのスペースで区切られた番号含有 CをI (1≤ C I ≤3)、 V I (1≤ V iが ≤ nが)、 C I 操作型である(文で与えられた番号付けに従います)、及び V iは、 操作が行われた頂点です。
与えられたグラフが木であることが保証されています。
頂点が空の場合、各タイプ3の運用別の行にプリント1頂点が一杯になった場合、および0。クエリが入力に与えられた順序でのクエリに対する回答を印刷します。
5
1 2
5 1
2 3
4 2
12
1 1
2 3
3 1
3 2
3 3
3 4
1 2
2 4
3 1
3 3
3 4
3 5
0
0
0
1
0
1
0
1
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 const int N=5e5+10; 7 int sum[N*4],lazy[N*4];//线段树 8 int n,m,r,mod;//节点数,操作数,根节点,模数 9 int first[N],tot; //邻接表 10 //重儿子,每个节点新编号,父亲,编号,深度,子树个数,所在重链的顶部 11 int son[N],id[N],fa[N],cnt,deep[N],size[N],top[N]; 12 int w[N],wt[N];// 初始点权,新编号点权 13 int res=0;//查询答案 14 15 struct edge{ 16 int v,next; 17 }e[N*4]; 18 19 void add_edge(int u,int v){ 20 e[tot].v=v; 21 e[tot].next=first[u]; 22 first[u]=tot++; 23 } 24 25 void init(){ 26 memset(first,-1,sizeof(first)); 27 tot=0; 28 cnt=0; 29 } 30 31 int pushup(int rt){ 32 sum[rt]=(sum[rt*2]&&sum[rt*2+1]); 33 } 34 35 void pushdown(int rt,int m){ 36 if(lazy[rt]!=-1){ 37 lazy[rt*2]=lazy[rt]; 38 lazy[rt*2+1]=lazy[rt]; 39 sum[rt*2]=lazy[rt]; 40 sum[rt*2+1]=lazy[rt]; 41 lazy[rt]=-1; 42 } 43 } 44 45 void build(int l,int r,int v){ 46 lazy[v]=-1; 47 if(l==r){ 48 sum[v]=0; 49 return ; 50 } 51 int mid=(l+r)/2; 52 build(l,mid,v*2); 53 build(mid+1,r,v*2+1); 54 pushup(v); 55 } 56 57 void update(int L,int R,int c,int l,int r,int rt){ 58 if(L<=l&&r<=R){ 59 lazy[rt]=c; 60 sum[rt]=c; 61 return; 62 } 63 pushdown(rt,r-l+1); 64 int m=(l+r)/2; 65 if(L<=m) update(L,R,c,l,m,rt*2); 66 if(R>m) update(L,R,c,m+1,r,rt*2+1); 67 pushup(rt); 68 } 69 70 71 void dfs1(int u,int f,int d){ 72 deep[u]=d; 73 fa[u]=f; 74 size[u]=1; 75 int maxson=-1; 76 for(int i=first[u];~i;i=e[i].next){ 77 int v=e[i].v; 78 if(v==f) continue; 79 dfs1(v,u,d+1); 80 size[u]+=size[v]; 81 if(size[v]>maxson){ 82 son[u]=v; 83 maxson=size[v]; 84 } 85 } 86 } 87 88 void dfs2(int u,int topf){ 89 id[u]=++cnt; 90 wt[cnt]=w[u]; 91 top[u]=topf; 92 if(!son[u]) return ; 93 dfs2(son[u],topf); 94 for(int i=first[u];~i;i=e[i].next){ 95 int v=e[i].v; 96 if(v==fa[u]||v==son[u]) continue; 97 dfs2(v,v); 98 } 99 } 100 101 102 void updrange(int x,int y,int k){ 103 while(top[x]!=top[y]){ 104 if(deep[top[x]]<deep[top[y]]) swap(x,y); 105 update(id[top[x]],id[x],0,1,n,1); 106 x=fa[top[x]]; 107 } 108 if(deep[x]>deep[y]) swap(x,y); 109 update(id[x],id[y],0,1,n,1); 110 } 111 112 void upson(int x,int k){ 113 update(id[x],id[x]+size[x]-1,1,1,n,1); 114 } 115 116 int query(int L,int R,int l,int r,int rt){ 117 if(L<=l&&r<=R){ 118 return sum[rt]; 119 } 120 pushdown(rt,r-l+1); 121 int m=(l+r)/2; 122 if(L<=m) return query(L,R,l,m,rt*2); 123 else if(R>m) return query(L,R,m+1,r,rt*2+1); 124 } 125 126 127 128 129 130 131 int main(){ 132 int u,v; 133 scanf("%d",&n); 134 init(); 135 for(int i=1;i<=n-1;i++){ 136 scanf("%d%d",&u,&v); 137 add_edge(u,v); 138 add_edge(v,u); 139 } 140 dfs1(1,0,1); 141 dfs2(1,1); 142 build(1,n,1); 143 scanf("%d",&m); 144 while(m--){ 145 int op,x,y,z; 146 scanf("%d",&op); 147 if(op==1){ 148 scanf("%d",&x); 149 upson(x,1); 150 } 151 else if(op==2){ 152 scanf("%d",&x); 153 updrange(1,x,0); 154 } 155 else if(op==3){ 156 scanf("%d",&x); 157 if(query(id[x],id[x],1,n,1)==0) printf("0\n"); 158 else printf("1\n"); 159 } 160 } 161 }
ツリーは、チェーンを分割します、この質問は、次元削減の打撃であります