High-level ancients
Time Limit: 20 Sec
Memory Limit: 256 MB
题目连接
http://acm.uestc.edu.cn/#/problem/show/574
Description
Love8909 is keen on the history of Kingdom ACM. He admires the heroic undertakings of Lxhgww and Haibo. Inspired by those sagas, Love8909 picked up his courage and tried to build up his own kingdom. He named it as A230.
After hard working for several years, Love8909 is about to fulfill his dream. However, there is still one thing to do: setting up the defense network. As Kingdom EDC looks at territory and people of A230 fiercely as a tiger does, Love8909 has to make it as soon as possible.
The defense network Love8909 wants to use is the same as the one used by Lxhgww and Haibo. He also connects all cities with roads which form a tree structure, and the capital city is City 1, which is the root of this tree. Love8909 sends commands to inform cities to add soldiers. The command, being same to those of the ancients, with two values, X and K, means sending K soldiers to City X, sending K+1 soldiers to sons of City X, sending K+2 soldiers to sons of sons of City X and so on. Initially there are no soldiers in any city.
Love8909 may adjust the arrangement of soldiers ever and again. He asks questions about how many soldiers in the subtree rooted at City X. A subtree rooted at City X includes City X itself and all of its descendants. As Love8909‘s military counselor, you are responsible to complete all his commands and answer his questions.
Input
The first line of the input will be an integer T (T≤20) indicating the number of cases.
For each case, the first line contains two integers: N P, representing the number of cities in A230 and number of operations given by love8909.
The next line lists N−1 integers, in which the ith number, denoted as Xi+1, represents there is a road from City Xi+1 to City i+1. Note that the City 1has been omitted. 1≤Xi+1≤N for 2≤i≤N.
Then P lines follow, each gives an operation. Each operation belongs to either kind:
A X K
. An adding-soldier command.Q X
. A question about how many soldiers in the subtree rooted at City X.
We guarantee that the cities form a rooted tree and the root is at City 1, which is the capital.
1≤N≤50000, 1≤P≤100000, 1≤X≤N, 0≤K≤1000.
Output
For each case, print Case #k:
first in a single line, in which k represents the case number which starts from 1. Then for each Query X
operation, print the answer in a single line.
Sample Input
1 7 10 1 1 2 2 5 5 Q 1 A 2 1 Q 1 Q 2 Q 5 A 5 0 Q 5 A 3 1 Q 1 Q 2
Sample Output
Case #1: 0 11 11 8 10 14 13
HINT
题意
给你一棵以1为根的树,有两个操作
1.A x k,让x增加k,x的儿子增加k+1,x的孙子增加k+2....x的t代儿子增加k+t
2.Q x , 查询x的子树的权值和是多少
题解:
看到处理子树问题,很显然的dfs序
dfs离散之后,维护线段树区间和,区间更新
我们很容易看出,他的更新是和deep有关的,deep越深的,更新越大
那么我们对于每个节点i,先区间更新y-deep[x],然后再使得更新一次,使得每个节点i增加deep[i]就好了
这样每个属于x的子树的都更新了 y - deep[x] + deep[i]
代码:
#include<iostream> #include<stdio.h> #include<vector> using namespace std; #define maxn 100010 struct Node { int l,r,d,val; }; Node node[maxn]; vector<int>Q[maxn]; int TTT[maxn]; int cnt = 1; void dfs(int x,int fa,int d) { node[x].l = cnt; node[x].d = d; TTT[cnt]=x; cnt++; for(int i=0;i<Q[x].size();i++) { int v = Q[x][i]; if(v==fa)continue; dfs(v,x,d+1); } node[x].r = cnt; } int d[maxn]; struct Seg { typedef long long SgTreeDataType; struct treenode { int L , R ; SgTreeDataType sum , lazy1 , lazy2; }; treenode tree[maxn*4]; inline void push_down(int o) { SgTreeDataType lazyval1 = tree[o].lazy1; SgTreeDataType lazyval2 = tree[o].lazy2; if(lazyval1==0&&lazyval2==0)return; int L = tree[o].L , R = tree[o].R; int mid = (L+R)/2; tree[2*o].lazy1+=lazyval1;tree[2*o].sum+=lazyval1*(mid-L+1); tree[2*o+1].lazy1+=lazyval1;tree[2*o+1].sum+=lazyval1*(R-mid); tree[2*o].lazy2+=lazyval2;tree[2*o].sum+=lazyval2*d[2*o]; tree[2*o+1].lazy2+=lazyval2;tree[2*o+1].sum+=lazyval2*d[2*o+1]; tree[o].lazy1 = tree[o].lazy2 = 0; } inline void push_up(int o) { tree[o].sum = tree[2*o].sum + tree[2*o+1].sum; } inline void build_tree(int L , int R , int o) { tree[o].L = L , tree[o].R = R,tree[o].sum = tree[o].lazy1 = tree[o].lazy2 = 0; if(L==R) d[o]=node[TTT[L]].d; if (R > L) { int mid = (L+R) >> 1; build_tree(L,mid,o*2); build_tree(mid+1,R,o*2+1); d[o]=d[o*2]+d[o*2+1]; } } inline void updata1(int QL,int QR,SgTreeDataType v,int o) { int L = tree[o].L , R = tree[o].R; if (QL <= L && R <= QR) { tree[o].lazy1 += v; tree[o].sum += v * (R-L+1); } else { push_down(o); int mid = (L+R)>>1; if (QL <= mid) updata1(QL,QR,v,o*2); if (QR > mid) updata1(QL,QR,v,o*2+1); push_up(o); } } inline void updata2(int QL,int QR,SgTreeDataType v,int o) { int L = tree[o].L , R = tree[o].R; if (QL <= L && R <= QR) { tree[o].lazy2+=v; tree[o].sum+=v*d[o]; } else { push_down(o); int mid = (L+R)>>1; if (QL <= mid) updata2(QL,QR,v,o*2); if (QR > mid) updata2(QL,QR,v,o*2+1); push_up(o); } } inline SgTreeDataType query(int QL,int QR,int o) { int L = tree[o].L , R = tree[o].R; if (QL <= L && R <= QR) return tree[o].sum; else { push_down(o); int mid = (L+R)>>1; SgTreeDataType res = 0; if (QL <= mid) res += query(QL,QR,2*o); if (QR > mid) res += query(QL,QR,2*o+1); push_up(o); return res; } } }T; int main() { int t;scanf("%d",&t); for(int cas=1;cas<=t;cas++) { printf("Case #%d:\n",cas); int n,q; scanf("%d%d",&n,&q); for(int i=0;i<=n;i++)Q[i].clear(),node[i].val=0; cnt = 1; for(int i=2;i<=n;i++) { int x,y;scanf("%d",&x); y=i; Q[x].push_back(y); Q[y].push_back(x); } dfs(1,-1,1); T.build_tree(1,n,1); string ch; while(q--) { cin>>ch; if(ch[0]==‘Q‘) { int x;scanf("%d",&x); printf("%lld\n",T.query(node[x].l,node[x].r-1,1)); } else { int x,y;scanf("%d%d",&x,&y); T.updata1(node[x].l,node[x].r-1,y-node[x].d,1); T.updata2(node[x].l,node[x].r-1,1,1); } } } }