苹果树

题目描述 Description

在卡卡的房子外面,有一棵苹果树。每年的春天,树上总会结出很多的苹果。卡卡非常喜欢吃苹果,所以他一直都精心的呵护这棵苹果树。我们知道树是有很多分叉点的,苹果会长在枝条的分叉点上面,且不会有两个苹果结在一起。卡卡很想知道一个分叉点所代表的子树上所结的苹果的数目,以便研究苹果树哪些枝条的结果能力比较强。

卡卡所知道的是,每隔一些时间,某些分叉点上会结出一些苹果,但是卡卡所不知道的是,总会有一些调皮的小孩来树上摘走一些苹果。

于是我们定义两种操作:

C x

表示编号为x的分叉点的状态被改变(原来有苹果的话,就被摘掉,原来没有的话,就结出一个苹果)

G x

查询编号为x的分叉点所代表的子树中有多少个苹果

我们假定一开始的时候,树上全都是苹果,也包括作为根结点的分叉1。

输入描述 Input Description

第一行一个数N (n<=100000)

接下来n-1行,每行2个数u,v,表示分叉点u和分叉点v是直接相连的。

再接下来一行一个数M,(M<=100000)表示询问数

接下来M行,表示询问,询问的格式如题目所述Q x或者C x

输出描述 Output Description

对于每个Q x的询问,请输出相应的结果,每行输出一个

样例输入 Sample Input

3

1 2

1 3

3

Q 1

C 2

Q 1

样例输出 Sample Output

3

2

题解:

  由于给定的是一棵树,要用线段树来维护的话必须是一个序列,考虑到对图或树进行深度优先搜索求出的发现时间和完成时间(时间戳)会形成一个括号化结构,这样就很好找出某个节点它的所有孩子,然后再用线段树进行单点修改,区间查询即可。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<cstring>
  7 #include<vector>
  8 #include<queue>
  9 using namespace std;
 10 const int maxn=100010;
 11 inline int read(){
 12     int x=0,f=1;char ch=getchar();
 13     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 14     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 15     return x*f;
 16 }
 17 int N,M;
 18 int tot=1;
 19 vector<int> to[maxn];
 20 int a[maxn*8],b[maxn*8];
 21 int fa[maxn*8];
 22 char s[10];
 23 struct POS{
 24     int l,r;
 25     int cnt;
 26 }pos[maxn*8];
 27 inline void dfs(int rt){
 28     for(int i=0;i<to[rt].size();i++){
 29         int y=to[rt][i];
 30         if(y!=fa[rt]){
 31             a[++tot]=y; fa[y]=rt;    
 32             dfs(y);
 33         }
 34     }
 35     if(to[rt].size()>1) a[++tot]=rt;
 36 }
 37 struct node{
 38     int l,r;
 39     int sum;
 40 }seg[maxn*8];
 41 inline void build(int rt,int l,int r){
 42     seg[rt].l=l; seg[rt].r=r;
 43     if(l==r){
 44         seg[rt].sum=b[l]; return ;
 45     }
 46     int mid=(l+r)>>1;
 47     build(rt*2,l,mid); build(rt*2+1,mid+1,r);
 48     seg[rt].sum=seg[rt*2].sum+seg[rt*2+1].sum;
 49 }
 50 inline void change(int rt,int tar){
 51     if(seg[rt].l==seg[rt].r){
 52         if(seg[rt].sum==1) seg[rt].sum=0;
 53         else seg[rt].sum=1;
 54         return ;
 55     }
 56     int mid=(seg[rt].l+seg[rt].r)>>1;
 57     if(tar<=mid) change(rt*2,tar);
 58     else change(rt*2+1,tar);
 59     seg[rt].sum=seg[rt*2].sum+seg[rt*2+1].sum;
 60 }
 61 inline int query(int rt,int l,int r){
 62     if(l<=seg[rt].l&&seg[rt].r<=r){
 63         return seg[rt].sum;
 64     }
 65     int mid=(seg[rt].l+seg[rt].r)>>1;
 66     int ans=0;
 67     if(l<=mid) ans+=query(rt*2,l,r);
 68     if(mid+1<=r) ans+=query(rt*2+1,l,r);
 69     return ans; 
 70 }
 71 int main(){
 72    // freopen("apple.in","r",stdin);
 73    // freopen("apple.out","w",stdout);
 74     N=read();
 75     for(int i=1;i<=N-1;i++){
 76         int u=read(),v=read();
 77         to[u].push_back(v); to[v].push_back(u);
 78     }
 79     fa[1]=-1; a[tot]=1; dfs(1);
 80     for(int i=1;i<=tot;i++){
 81         int temp=++pos[a[i]].cnt;
 82         if(temp==1) pos[a[i]].l=i;
 83         else pos[a[i]].r=i;
 84     }
 85     for(int i=1;i<=N;i++) b[pos[i].l]=1;
 86     build(1,1,tot);
 87     M=read();
 88     for(int i=1,tmp;i<=M;i++){
 89         scanf("%s",s);
 90         if(s[0]=='Q'){
 91             tmp=read();
 92             if(pos[tmp].cnt==1) cout<<query(1,pos[tmp].l,pos[tmp].l)<<endl;
 93             else cout<<query(1,pos[tmp].l,pos[tmp].r)<<endl;
 94         }
 95         else{
 96             tmp=read();
 97             change(1,pos[tmp].l);
 98         }
 99     }
100     return 0;
101 }

 

posted @ 2015-11-29 13:29  CXCXCXC  阅读(407)  评论(0编辑  收藏  举报