There is a rooted tree with n nodes, number from 1-n. Root’s number is 1.Each node has a value ai.
Initially all the node’s value is 0.
We have q operations. There are two kinds of operations.
1 v x k : a[v]+=x , a[v’]+=x-k (v’ is child of v) , a[v’’]+=x-2*k (v’’ is child of v’) and so on.
2 v : Output a[v] mod 1000000007(10^9 + 7).
First line contains an integer T (1 ≤ T ≤ 3), represents there are T test cases.
In each test case:
The first line contains a number n.
The second line contains n-1 number, p2,p3,…,pn . pi is the father of i.
The third line contains a number q.
Next q lines, each line contains an operation. (“1 v x k” or “2 v”)
1 ≤ n ≤ 3*10^5
1 ≤ pi < i
1 ≤ q ≤ 3*10^5
1 ≤ v ≤ n; 0 ≤ x < 10^9 + 7; 0 ≤ k < 10^9 + 7
For each operation 2, outputs the answer.
1 3 1 1 3 1 1 2 1 2 1 2 2Sample Output
2 1
看了网上的题解博客,弄懂思路,经过不断调试和修改,终于在规定时间ac了。
思路:
树链剖分。
用dfs序分割出每一颗子树,编号自动从1到n,不用操作,在一条链上的点都是连续的,而且可以一一对应到线段树上,因为题目刚开始没有初始值,所以也不用建树,最后的查询也不是对某一条链进行查询,直接是单点查询,所以,应该也称不上熟练剖分吧,都说是dfs序+线段树。
总之还是dfs序好些,以后再写一写熟练剖分的代码吧。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #define lson rt1<<1,l,m #define rson rt1<<1|1,m+1,r #define LL long long using namespace std; const LL maxn=310000; const LL mod=1e9+7; vector<LL>G[maxn]; LL deep[maxn]; LL st[maxn],en[maxn]; LL ans=0; LL tem=0; //**************** LL sum[maxn*4],sumk[maxn*4]; void dfs(LL x) { deep[x]=ans; st[x]=tem++; ans++; for(LL i=0;i<G[x].size();i++) { LL v=G[x][i]; dfs(v); } ans--; en[x]=tem-1; } void update(LL u,LL x,LL k,LL lt,LL rt,LL rt1,LL l,LL r) { if(lt<=l&&r<=rt) { sum[rt1]=(sum[rt1]+x+deep[u]*k)%mod; sumk[rt1]=(sumk[rt1]+k)%mod; return; } LL m=(r+l)>>1; if(lt<=m)update(u,x,k,lt,rt,lson); if(rt>m)update(u,x,k,lt,rt,rson); } LL quert(LL u,LL L,LL R,LL rt1,LL l,LL r) { if(L<=l&&r<=R) { return (sum[rt1]-(sumk[rt1]*deep[u])%mod)%mod; } LL m=(l+r)>>1; if(L<=m)return(quert(u,L,R,lson)+sum[rt1]-(sumk[rt1]*deep[u])%mod)%mod; else return(quert(u,L,R,rson)+sum[rt1]-(sumk[rt1]*deep[u])%mod)%mod; } int main() { LL t; scanf("%I64d",&t); while(t--) { memset(deep,0,sizeof(deep)); memset(sum,0,sizeof(sum)); memset(sumk,0,sizeof(sumk)); memset(st,0,sizeof(st)); memset(en,0,sizeof(en)); ans=0,tem=1; LL n; scanf("%I64d",&n); for(int i=1;i<=n;i++)G[i].clear(); LL u; for(int i=2;i<=n;i++) { scanf("%I64d",&u); G[u].push_back(i); } LL m,f,x,k; LL lt,rt; scanf("%I64d",&m); ans=0; dfs(1); while(m--) { scanf("%I64d",&f); if(f==1) { scanf("%I64d%I64d%I64d",&u,&x,&k); lt=st[u]; rt=en[u]; update(u,x,k,lt,rt,1,1,n); } else { scanf("%I64d",&u); lt=st[u]; rt=st[u]; printf("%I64d\n",(quert(u,lt,rt,1,1,n)+mod)%mod); } } } return 0; }