1. 程式人生 > >【codevs1228】蘋果樹【線段樹+dfs序】

【codevs1228】蘋果樹【線段樹+dfs序】

題目描述 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
題解:我們知道,在一棵子樹中dfs序是連續的。所以先求出這棵樹的dfs序,記錄一下每個節點在dfs序中的位置。再記錄一下每棵子樹中dfs序的最大值。然後根據dfs序建一棵線段樹。剩下就和裸線段樹一樣了。。
注意資料中有換行,非常坑人。。。

#include<iostream>
#include<cstdio>
using namespace std;
int t[1000001],mx[100001],pos[1000001],point[1000001],next[1000001],cnt,sz;
struct use{
    int st,en;
}b[1000001];
int n,u,v,m,aa,bb;
char ch;
void add(int x,int y)
{
   next[++cnt]=point[x];point[x]=cnt;
   b[cnt].st=x;b[cnt].en=y;
}
void dfs(int x,int fa)
{
   pos
[x]=++sz;mx[x]=sz; for (int i=point[x];i;i=next[i]) { if (b[i].en==fa) continue; dfs(b[i].en,x); mx[x]=max(mx[x],mx[b[i].en]); } } void build(int k,int l,int r) { int mid; if (l==r){t[k]=1;return;}; mid=(l+r)/2; build(2*k,l,mid); build(2*k+1,mid+1,r); t[k]=t[2
*k]+t[2*k+1]; } void change(int k,int l,int r,int x) { int mid; if (l==r&&l==x) { if (t[k]==1) t[k]=0;else t[k]=1; return; } mid=(l+r)/2; if (x<=mid) change(2*k,l,mid,x); if (x>mid) change(2*k+1,mid+1,r,x); t[k]=t[2*k]+t[2*k+1]; } int qsum(int k,int l,int r,int ll,int rr) { int mid,ans(0); if (ll<=l&&r<=rr) return t[k]; mid=(l+r)/2; if (ll<=mid) ans+=qsum(2*k,l,mid,ll,rr); if (mid<rr) ans+=qsum(2*k+1,mid+1,r,ll,rr); return ans; } int main() { scanf("%d",&n); for (int i=1;i<n;i++){scanf("%d%d",&u,&v);add(u,v);add(v,u);} dfs(1,0);build(1,1,n);cin>>m; for (int i=1;i<=m;i++) { scanf("%*c%*c%c%d",&ch,&aa); if (ch=='C') { change(1,1,n,pos[aa]); } if (ch=='Q') { printf("%d\n",qsum(1,1,n,pos[aa],mx[aa])); } } }