Codeforces Round #200 (Div. 1) D:http://codeforces.com/problemset/problem/343/D
题意:给你一颗有根树,树的每个节点有一个装水的东西,然后付亲的水可以流向儿子。一开始树上每个节点都是空的,然后会有两种操作。1 v,表示把v节点为子树的每个点都灌满水,2 v,表示v及v的祖先都清空。3 v是询问 v节点是否为空,为空输出0,否则输出1.
题解:首先,树上操作可以通过DFS,然后转化成数组操作。3操作来说,只要v的子树中有一个0,那么v一定是0,所以把单点查询,转化成了区间查询。2操作来说,我们可以只进行单点更新,即只对v这个节点操作。1操作的时候,就是区间更新,但是这里首先要查询v中是否有0,因为2操作只到了点。加入说,之前 2 v,那么v及其父亲应该是0的,这时候如果1,v的话,那么必须要把v的父亲变为0.这里有两种实现。先说一种好写。set运用。我们一开始把树上的每个节点都放进set,表示每个几点都是0.对于操作1.来说,首先我们要查询是否有0,Q.lower_bound(ll[temp]),如果找到并且这个数的位置不超过rr[temp],那么v的父亲要变成0,即可v的父亲查到set中,同时把那些变成1的元素从set中删除,Q.erase(Q.lower_bound(ll[temp]),Q.upper_bound(rr[temp]));3操作类似。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<set> 6 using namespace std; 7 const int N=5e5+10; 8 int head[N],now; 9 int fa[N],ll[N],rr[N],cnt; 10 set<int>Q; 11 void init(){ 12 memset(head,-1,sizeof(head)); 13 memset(rr,0,sizeof(rr)); 14 memset(ll,0,sizeof(ll)); 15 memset(fa,0,sizeof(fa)); 16 now=0; 17 cnt=0; 18 } 19 struct Node{ 20 int v; 21 int next; 22 }edge[N*2]; 23 void add(int u,int v){ 24 edge[cnt].v=v; 25 edge[cnt].next=head[u]; 26 head[u]=cnt++; 27 } 28 void DFS(int u,int f){ 29 ll[u]=rr[u]=++now; 30 Q.insert(now); 31 fa[u]=f; 32 for(int i=head[u];i!=-1;i=edge[i].next){ 33 int v=edge[i].v; 34 if(v!=f) 35 DFS(v,u); 36 } 37 rr[u]=now; 38 } 39 int n,m,t1,t2; 40 int main(){ 41 while(~scanf("%d",&n)){ 42 init(); 43 for(int i=1;i<n;i++){ 44 scanf("%d%d",&t1,&t2); 45 add(t1,t2);add(t2,t1); 46 } 47 DFS(1,0); 48 scanf("%d",&m); 49 for(int i=1;i<=m;i++){ 50 scanf("%d%d",&t1,&t2); 51 if(t1==1){ 52 bool flag=false; 53 set<int>::iterator it=Q.lower_bound(ll[t2]); 54 if(it==Q.end()||(*it)>rr[t2]) 55 flag=true; 56 Q.erase(Q.lower_bound(ll[t2]),Q.upper_bound(rr[t2])); 57 if(!flag&&t2!=1) 58 Q.insert(ll[fa[t2]]); 59 } 60 else if(t1==2){ 61 Q.insert(ll[t2]); 62 } 63 else { 64 set<int>::iterator it=Q.lower_bound(ll[t2]); 65 if(it==Q.end()||(*it)>rr[t2]) 66 printf("1\n"); 67 else 68 printf("0\n"); 69 } 70 } 71 } 72 }