WZJ的数据结构(负十) |
难度级别:D; 运行时间限制:5000ms; 运行空间限制:51200KB; 代码长度限制:2000000B |
试题描述
|
给你一个N个节点的有根树,从1到N编号,根节点为1并给出每个点的权值与父亲节点。请你设计一个数据结构,进行以下两种操作: F x v : 将节点x的子树的每个节点权值+v Q x : 询问节点x到其根的路径上的节点权值之和 |
输入
|
第一行一个正整数N。
接下来N-1行每行一个正整数,分别表示节点2-n的父亲节点编号。 接下来一行N个正整数,表示每个节点的初始权值。 再接下来一行一个正整数M,表示操作的总数。 操作分为以下两种类型。 (1)"Q x"表示询问节点x到其根的路径上的节点权值之和. (2)"F x v"表示将节点x的子树的每个节点权值+v. |
输出
|
对于每一个操作类型为Q的操作,输出一行一个整数,表示此次询问的答案。
|
输入示例
|
6
1 1 2 2 2 4 5 7 1 2 3 4 Q 2 F 1 3 Q 2 Q 5 |
输出示例
|
9
15 20 |
其他说明
|
1<=N,M<=100000
1<=pi,x<=N 1<=wi<=10^6 1<=v<=1000 |
今天跟健学了DFS序。。。原来就这么回事,注意好符号、出入。
还有,以后的AddEdge注意好顺序!!!
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU putchar(' ') 8 #define ENT putchar(' ') 9 using namespace std; 10 typedef long long LL; 11 const int maxn=200000+10,maxn3=600000+10,inf=-1u>>1; 12 LL addv[maxn3],sumv[maxn3],siz[maxn3],_sum;int n,Q,sig[maxn],A[maxn],si[maxn],so[maxn],cz=0,ql,qr,cv; 13 struct Tedge{int x,y,next;}adj[maxn];int ms=0,fch[maxn]; 14 void AddEdge(int u,int v){adj[++ms]=(Tedge){u,v,fch[u]};fch[u]=ms;return;} 15 void dfs(int u){ 16 si[u]=++cz;sig[cz]=1; 17 for(int i=fch[u];i;i=adj[i].next) dfs(adj[i].y); 18 so[u]=++cz;sig[cz]=-1; 19 return; 20 } 21 void maintain(int o,int L,int R){ 22 int lc=o<<1,rc=lc|1; 23 if(L<R) sumv[o]=sumv[lc]+sumv[rc]; else sumv[o]=0; 24 sumv[o]+=addv[o]*siz[o];return; 25 } 26 void build(int o,int L,int R){ 27 if(L==R) addv[o]=A[L],siz[o]=sig[L]; 28 else{ 29 int M=L+R>>1,lc=o<<1,rc=lc|1; 30 build(lc,L,M);build(rc,M+1,R); 31 siz[o]=siz[lc]+siz[rc]; 32 } maintain(o,L,R);return; 33 } 34 void update(int o,int L,int R){ 35 if(ql<=L&&R<=qr) addv[o]+=cv; 36 else{ 37 int M=L+R>>1,lc=o<<1,rc=lc|1; 38 if(ql<=M) update(lc,L,M); 39 if(qr>M) update(rc,M+1,R); 40 } maintain(o,L,R);return; 41 } 42 void query(int o,int L,int R,int add){ 43 if(ql<=L&&R<=qr) _sum+=add*siz[o]+sumv[o]; 44 else{ 45 int M=L+R>>1,lc=o<<1,rc=lc|1; 46 if(ql<=M) query(lc,L,M,add+addv[o]); 47 if(qr>M) query(rc,M+1,R,add+addv[o]); 48 } return; 49 } 50 inline int read(){ 51 int x=0,sig=1;char ch=getchar(); 52 while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();} 53 while(isdigit(ch))x=10*x+ch-'0',ch=getchar(); 54 return x*=sig; 55 } 56 inline void write(int x){ 57 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 58 int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; 59 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 60 } 61 inline void write(LL x){ 62 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 63 int len=0;LL buf[15];while(x)buf[len++]=x%10,x/=10; 64 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 65 } 66 inline char readc(){ 67 char tp;for(tp=getchar();!isalpha(tp);tp=getchar());return tp; 68 } 69 void init(){ 70 n=read(); 71 for(int i=2;i<=n;i++) AddEdge(read(),i); dfs(1); 72 for(int i=1;i<=n;i++) A[si[i]]=A[so[i]]=read(); build(1,1,n<<1); 73 return; 74 } 75 void work(){ 76 Q=read(); 77 while(Q--){ 78 if(readc()=='Q'){ 79 _sum=0; 80 ql=1;qr=si[read()];query(1,1,n<<1,0); 81 write(_sum);ENT; 82 } 83 else{ 84 ql=read(); 85 qr=so[ql];ql=si[ql];cv=read(); 86 update(1,1,n<<1); 87 } 88 } 89 return; 90 } 91 void print(){ 92 return; 93 } 94 int main(){init();work();print();return 0;}