题目链接:
F - Change
题目大意:
题意: 给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作
(1) 1 v k x : a[v] += x, a[v '] += x – k(v '为v的儿子), a[v ' '] += x – 2 * k(v ' '是v '的儿子) ... ;
(2) 2 v : 输出a[v] % (1e9 + 7);
具体思路:dfs序+线段树
a[v'']=a[v'']+x-k*(depth[v'']-depth[v])=a[v'']+x-k*depth[v"]+k*depth[v]=(a[v"]+k*depth[v]) - k*depth[v""].
第一个括号里面用一个线段树维护,第二个括号里面用另一个线段树维护就可以了。
具体求值的时候:对于一次增加操作,节点x增加的值其实就是x-(deep[x]-deep[v])*k。(deep[v]为该次修改的根节点)。
AC代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<vector> 4 #include<cstring> 5 using namespace std; 6 # define ll long long 7 # define lson l,mid,rt<<1 8 # define rson mid+1,r,rt<<1|1 9 const int maxn = 3e5+100; 10 const int mod =1e9+7; 11 ll tree1[maxn<<2],tree2[maxn<<2]; 12 int dfsord,n; 13 vector<int>edge[maxn]; 14 int st[maxn],ed[maxn],depth[maxn]; 15 int Scan() 16 { 17 int res = 0, ch, flag = 0; 18 if((ch = getchar()) == '-') 19 flag = 1; 20 else if(ch >= '0' && ch <= '9') 21 res = ch - '0'; 22 while((ch = getchar()) >= '0' && ch <= '9' ) 23 res = res * 10 + ch - '0'; 24 return flag ? -res : res; 25 } 26 27 ll Scan_l() 28 { 29 ll res = 0; 30 int ch, flag = 0; 31 if((ch = getchar()) == '-') 32 flag = 1; 33 else if(ch >= '0' && ch <= '9') 34 res = ch - '0'; 35 while((ch = getchar()) >= '0' && ch <= '9' ) 36 res = res * 10 + ch - '0'; 37 return flag ? -res : res; 38 } 39 void init() 40 { 41 for(int i=0; i<n; i++) 42 { 43 edge[i].clear(); 44 } 45 dfsord=0; 46 memset(tree1,0,sizeof(tree1)); 47 memset(tree2,0,sizeof(tree2)); 48 } 49 void dfs(int cur,int fa,int dep) 50 { 51 st[cur]=ed[cur]=++dfsord; 52 depth[dfsord]=dep+1; 53 for(int i=0; i<edge[cur].size(); i++) 54 { 55 int to=edge[cur][i]; 56 if(to==fa) 57 continue; 58 dfs(to,cur,dep+1); 59 } 60 ed[cur]=dfsord; 61 } 62 void down(int rt) 63 { 64 tree1[rt<<1]=(tree1[rt<<1]+tree1[rt]+mod)%mod; 65 tree1[rt<<1|1]=(tree1[rt<<1|1]+tree1[rt]+mod)%mod; 66 tree2[rt<<1]=(tree2[rt<<1]+tree2[rt]+mod)%mod; 67 tree2[rt<<1|1]=(tree2[rt<<1|1]+tree2[rt]+mod)%mod; 68 tree1[rt]=0,tree2[rt]=0; 69 } 70 void update(int l,int r,int rt,int L,int R,ll val1,ll val2) 71 { 72 if(L<=l&&R>=r) 73 { 74 tree1[rt]=(tree1[rt]+val1+mod)%mod; 75 tree2[rt]=(tree2[rt]+val2+mod)%mod; 76 return ; 77 } 78 down(rt); 79 int mid=(l+r)>>1; 80 if(L<=mid) 81 update(lson,L,R,val1,val2); 82 if(R>mid) 83 update(rson,L,R,val1,val2); 84 } 85 ll ask(int l,int r,int rt,int pos) 86 { 87 if(l==r) 88 { 89 return (tree1[rt]+tree2[rt]*depth[pos]%mod+mod)%mod; 90 } 91 int mid=(l+r)>>1; 92 down(rt); 93 if(pos<=mid) 94 return ask(lson,pos); 95 else 96 return ask(rson,pos); 97 } 98 int main() 99 { 100 int T,tmp; 101 T=Scan(); 102 while(T--) 103 { 104 n=Scan(); 105 init(); 106 for(int i=2; i<=n; i++) 107 { 108 tmp=Scan(); 109 edge[tmp].push_back(i); 110 } 111 int m; 112 dfs(1,0,0); 113 m=Scan(); 114 while(m--) 115 { 116 int op,v; 117 ll x,k; 118 op=Scan(); 119 if(op==1) 120 { 121 v=Scan(); 122 x=Scan_l(); 123 k=Scan_l(); 124 update(1,n,1,st[v],ed[v],x+k*depth[st[v]],-k); 125 } 126 else 127 { 128 v=Scan(); 129 ll ans=ask(1,n,1,st[v]); 130 ans=(ans%mod+mod)%mod; 131 printf("%lld ",ans); 132 } 133 } 134 } 135 return 0; 136 }