题目大意:
修改树上的节点,然后求子树的和。
思路分析:
dfs 重新编号,烂大街了。。。
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #define maxn 100005 #define lson num<<1,s,mid #define rson num<<1|1,mid+1,e using namespace std; int num[maxn]; int ed[maxn]; int tot[maxn<<2]; void pushup(int num) { tot[num]=tot[num<<1]+tot[num<<1|1]; } void build(int num,int s,int e) { if(s==e) { tot[num]=1; return; } int mid=(s+e)>>1; build(lson); build(rson); pushup(num); } void update(int num,int s,int e,int pos) { if(s==e) { tot[num]^=1; return; } int mid=(s+e)>>1; if(pos<=mid)update(lson,pos); else update(rson,pos); pushup(num); } int query(int num,int s,int e,int l,int r) { if(l<=s && r>=e){ return tot[num]; } int mid=(s+e)>>1; if(r<=mid)return query(lson,l,r); else if(l>mid)return query(rson,l,r); else return query(lson,l,mid)+query(rson,mid+1,r); } int id; int next[maxn<<1]; int head[maxn]; int to[maxn<<1]; void addedge(int u,int v) { id++; next[id]=head[u]; to[id]=v; head[u]=id; } int cnt=1; bool vis[maxn]; int dfs(int cur) { num[cur]=cnt++; ed[num[cur]]=num[cur]; for(int p=head[cur]; p ;p=next[p]) { if(vis[to[p]])continue; vis[to[p]]=true; ed[num[cur]] = max(ed[num[cur]],dfs(to[p])); } return ed[num[cur]]; } int main() { int n; while(scanf("%d",&n)!=EOF) { memset(vis,false,sizeof vis); memset(head,0,sizeof head); memset(ed,0,sizeof ed); id=0,cnt=1; for(int i=1;i<=n-1;i++) { int u,v; scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } vis[1]=true; dfs(1); int m; scanf("%d",&m); char str[2]; build(1,1,cnt-1); while(m--) { int op; scanf("%s%d",str,&op); if(str[0]=='Q') { printf("%d\n",query(1,1,cnt-1,num[op],ed[num[op]])); } else update(1,1,cnt-1,num[op]); } } return 0; } /* 4 1 2 1 3 2 4 2 5 */