DFS序可以把树转到区间上再用高级数据结构维护,比树链剖分好理解很多
一个闭区间就是一棵子树
POJ3321
1 #include<cstdio> 2 const int maxn=100005; 3 const int maxm=200005; 4 int n,m,id,cnt; 5 int g[maxn],q[maxn],st[maxn],ed[maxn]; 6 int lch[300005],rch[300005],sum[300005]; 7 struct Edge 8 { 9 int t,next; 10 }e[maxm]; 11 void insert(int u,int v) 12 { 13 ++cnt;e[cnt].t=v;e[cnt].next=g[u];g[u]=cnt; 14 ++cnt;e[cnt].t=u;e[cnt].next=g[v];g[v]=cnt; 15 } 16 void dfs(int x,int fa) 17 { 18 q[++id]=x; 19 st[x]=id; 20 for(int tmp=g[x];tmp;tmp=e[tmp].next) 21 if(e[tmp].t!=fa) dfs(e[tmp].t,x); 22 ed[x]=id; 23 } 24 void build(int k,int l,int r) 25 { 26 int mid=(l+r)>>1; 27 lch[k]=l;rch[k]=r; 28 if(l==r) 29 { 30 sum[k]=1; 31 return; 32 } 33 build(k<<1,l,mid); 34 build(k<<1|1,mid+1,r); 35 sum[k]=sum[k<<1]+sum[k<<1|1]; 36 } 37 int query(int k,int a,int b) 38 { 39 int l=lch[k],r=rch[k],mid=(l+r)>>1; 40 if(l==a&&r==b) return sum[k]; 41 if(b<=mid) return query(k<<1,a,b); 42 else if(a>mid) return query(k<<1|1,a,b); 43 else return query(k<<1,a,mid)+query(k<<1|1,mid+1,b); 44 } 45 void modify(int k,int x) 46 { 47 int l=lch[k],r=rch[k],mid=(l+r)>>1; 48 if(l==r) 49 { 50 sum[k]^=1; 51 return; 52 } 53 if(x<=mid) modify(k<<1,x); 54 else modify(k<<1|1,x); 55 sum[k]=sum[k<<1]+sum[k<<1|1]; 56 } 57 long long read() 58 { 59 long long x=0,f=1;char ch=getchar(); 60 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 61 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 62 return x*f; 63 } 64 int main() 65 { 66 n=read(); 67 for(int i=1;i<n;i++) 68 { 69 int u=read(),v=read(); 70 insert(u,v); 71 } 72 dfs(1,0); 73 m=read(); 74 char ch[10]; 75 build(1,1,n); 76 for(int i=1;i<=m;i++) 77 { 78 scanf("%s",ch+1); 79 int x=read(); 80 if(ch[1]=='Q') printf("%d ",query(1,st[x],ed[x])); 81 else modify(1,st[x]); 82 } 83 return 0; 84 }