CF877E Danil and a Part-time Job 線段樹維護dfs序
阿新 • • 發佈:2018-12-07
\(\color{#0066ff}{題目描述}\)
有一棵 n 個點的樹,根結點為 1 號點,每個點的權值都是 1 或 0
共有 m 次操作,操作分為兩種
get 詢問一個點 x 的子樹裡有多少個 1
pow 將一個點 x 的子樹中所有節點取反
對於每個 get 給出答案
\(\color{#0066ff}{輸入格式}\)
第一行一個整數 n
第二行共 n−1 個整數,第 i 個數 \(x_i\) 表示 \(x_i\) 是 i+1 的父親,
第三行給出每個點的初始權值
第四行一個整數 m
接下來 m 行為操作型別和位置
\(\color{#0066ff}{輸出格式}\)
對於每個 get 給出答案
\(\color{#0066ff}{輸入樣例}\)
4
1 1 1
1 0 0 1
9
get 1
get 2
get 3
get 4
pow 1
get 1
get 2
get 3
get 4
\(\color{#0066ff}{輸出樣例}\)
2
0
0
1
2
1
1
0
\(\color{#0066ff}{資料範圍與提示}\)
\(1\leq n \leq 200000,1\leq q\leq 200000\)
\(\color{#0066ff}{題解}\)
線段樹維護dfs序
同一子樹內dfs序連續
線段樹上修改查詢即可
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #define _ 0 #define LL long long #ifndef olinr inline char getc() { static char buf[100001],*p1=buf,*p2=buf; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100001,stdin),p1==p2)? EOF:*p1++; } #else #define getc() getchar() #endif inline LL in() { LL x=0,f=1; char ch; while(!isdigit(ch=getc()))(ch=='-')&&(f=-f); while(isdigit(ch)) x=x*10+(ch^48),ch=getc(); return x*f; } const int max=205005; int val[max],dfn[max],redfn[max],siz[max]; class SGT { private: struct node { int l,r; int val; node* ch[2]; bool tag; node(int l,int r,int val,int tag):l(l),r(r),val(val),tag(tag){} void upd() {val=ch[0]->val+ch[1]->val;} int mid() {return (l+r)>>1;} int siz() {return r-l+1;} void dwn() { if(!tag) return; ch[0]->val=ch[0]->siz()-ch[0]->val; ch[1]->val=ch[1]->siz()-ch[1]->val; ch[0]->tag^=1; ch[1]->tag^=1; tag=0; } }; typedef node* nod; public: nod root; void build(nod &o,int l,int r) { o=new node(l,r,0,0); if(l==r) return (void)(o->val=val[redfn[l]]); build(o->ch[0],l,o->mid()); build(o->ch[1],o->mid()+1,r); o->upd(); } void lazy(nod o,int l,int r) { if(o->r<l||o->l>r) return; if(l<=o->l&&o->r<=r) { o->tag^=1; o->val=o->siz()-o->val; return; } o->dwn(); lazy(o->ch[0],l,r),lazy(o->ch[1],l,r); o->upd(); } int query(nod o,int l,int r) { if(o->r<l||o->l>r) return 0; if(l<=o->l&&o->r<=r) return o->val; o->dwn(); return query(o->ch[0],l,r)+query(o->ch[1],l,r); } }s; struct node { int to; node *nxt; node(int to,node *nxt):to(to),nxt(nxt){} }; typedef node* nod; nod head[max]; int cnt; void add(int from,int to) { nod t=new node(to,head[from]); head[from]=t; } void dfs(int x,int f) { siz[x]=1; dfn[x]=++cnt; redfn[cnt]=x; for(nod i=head[x];i;i=i->nxt) if(i->to!=f) dfs(i->to,x),siz[x]+=siz[i->to]; } int n,m; int main() { n=in(); int x; for(int i=1;i<=n-1;i++) x=in(),add(x,i+1),add(i+1,x); for(int i=1;i<=n;i++) val[i]=in(); dfs(1,0); s.build(s.root,1,n); m=in(); char ch; while(m--) { while(!isalpha(ch=getc())); x=in(); if(ch=='g') printf("%d\n",s.query(s.root,dfn[x],dfn[x]+siz[x]-1)); else s.lazy(s.root,dfn[x],dfn[x]+siz[x]-1); } return 0; }