题目翻译(摘自洛谷)
疯狂科学家Mike培养了一颗有根树,由n个节点组成。每个节点是一个要么装满水要么为空的贮水容器. 树的节点用1~n编号,其中根节点为1.对于每个节点的容器,其子节点的容器均在这一容器下方,并且每个节点都由一根可以向下流水的管道与其子节点连接. Mike想要对这棵树做以下操作:
1将节点v注满水. 这样v和其子节点都会充满水.
2将节点v置空. 这样v及其祖先节点(从v到根节点的路径)都会被置空.
3查询当前节点v是否充满水.
初始时,所有节点都为空. Mike已经制定好了他的操作顺序. 在对树进行实验前,他决定先模拟一下操作. 请你帮助Mike得出他操作后的结果.
思路
裸树链剖分,区间修改,单点查询。
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int N=500005; 5 int n,cnt,dcnt,hd[N]; 6 struct edge 7 { 8 int to,nxt; 9 }v[2*N]; 10 struct node 11 { 12 int fa,son,sz,dep,tp,s,e; 13 }tr[N]; 14 struct segtree 15 { 16 int l,r,stat,tag; 17 }st[4*N]; 18 void addedge(int x,int y) 19 { 20 v[++cnt].to=y; 21 v[cnt].nxt=hd[x]; 22 hd[x]=cnt; 23 } 24 void dfs1(int u) 25 { 26 tr[u].sz=1; 27 for(int i=hd[u];i;i=v[i].nxt) 28 if(v[i].to!=tr[u].fa) 29 { 30 tr[v[i].to].fa=u; 31 tr[v[i].to].dep=tr[u].dep+1; 32 dfs1(v[i].to); 33 tr[u].sz+=tr[v[i].to].sz; 34 if(tr[v[i].to].sz>tr[tr[u].son].sz) 35 tr[u].son=v[i].to; 36 } 37 } 38 void dfs2(int u,int top) 39 { 40 tr[u].tp=top; 41 tr[u].s=++dcnt; 42 if(tr[u].son) 43 { 44 dfs2(tr[u].son,top); 45 for(int i=hd[u];i;i=v[i].nxt) 46 if(v[i].to!=tr[u].fa&&v[i].to!=tr[u].son) 47 dfs2(v[i].to,v[i].to); 48 } 49 tr[u].e=dcnt; 50 } 51 void build(int num,int l,int r) 52 { 53 st[num].l=l,st[num].r=r; 54 st[num].tag=-1; 55 if(l==r) 56 return ; 57 int mid=(l+r)/2; 58 build(2*num,l,mid),build(2*num+1,mid+1,r); 59 } 60 void pushdown(int num) 61 { 62 if(st[num].tag!=-1) 63 { 64 if(st[num].l!=st[num].r) 65 { 66 st[2*num].stat=st[2*num+1].stat=st[num].tag; 67 st[2*num].tag=st[2*num+1].tag=st[num].tag; 68 } 69 st[num].tag=-1; 70 } 71 } 72 void change(int num,int l,int r,int z) 73 { 74 if(l>st[num].r||r<st[num].l) 75 return ; 76 if(st[num].l>=l&&st[num].r<=r) 77 { 78 st[num].tag=st[num].stat=z; 79 return ; 80 } 81 pushdown(num); 82 change(2*num,l,r,z),change(2*num+1,l,r,z); 83 } 84 int query(int num,int x) 85 { 86 if(st[num].l>x||st[num].r<x) 87 return 0; 88 if(st[num].l==st[num].r) 89 return st[num].stat; 90 pushdown(num); 91 return query(2*num,x)+query(2*num+1,x); 92 } 93 void fnd(int x) 94 { 95 int f1=tr[x].tp; 96 while(f1!=1) 97 { 98 change(1,tr[f1].s,tr[x].s,0); 99 x=tr[f1].fa,f1=tr[x].tp; 100 } 101 change(1,1,tr[x].s,0); 102 } 103 int main() 104 { 105 scanf("%d",&n); 106 for(int i=1;i<=n-1;i++) 107 { 108 int x,y; 109 scanf("%d%d",&x,&y); 110 addedge(x,y),addedge(y,x); 111 } 112 dfs1(1); 113 dfs2(1,1); 114 build(1,1,n); 115 int q,x,y; 116 scanf("%d",&q); 117 while(q--) 118 { 119 scanf("%d%d",&x,&y); 120 switch(x) 121 { 122 case 1: 123 change(1,tr[y].s,tr[y].e,1); 124 break; 125 case 2: 126 fnd(y); 127 break; 128 case 3: 129 printf("%d ",query(1,tr[y].s)); 130 break; 131 } 132 } 133 return 0; 134 }