题意:
给出一棵以1为根的树,形式是从节点2开始给出每个节点的父亲节点;
然后是m次操作,操作分为两种,1 v,x,k,表示在以v为根的字数上添加,
添加的法则是看这个节点与v节点的距离为i的话,加上x-i*k;
2 v查询节点v的值。
思路一:
树链剖分,每个点保存两个值,一个是x+dep[i]*k,另外一个是k
查询的时候相当于它到根的链上(x+dep[i]*k)的和-dep[v]
∗
<script type="math/tex" id="MathJax-Element-4">*</script>(k的和)
时间复杂度:nlognlogn
思路二:
线段树,把上面的单点更新改成区间更新,单点查询就可以了,我好蠢啊
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+100;
typedef pair<int,int> PI;
const int MOD=1e9+7;
int head[N],tot,deep[N];
struct Edge{
int to,next;
}e[N];
void init(){
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int from,int to){
e[tot]=(Edge){to,head[from]};
head[from]=tot++;
}
int son[N],siz[N],fa[N],Count=0;
void dfs1(int u,int dep){
deep[u]=dep,son[u]=0,siz[u]=1;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].to;
fa[v]=u;
dfs1(v,dep+1);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
int top[N],id[N];
void dfs2(int u,int tp){
top[u]=tp;
id[u]=++Count;
if(son[u]!=0) dfs2(son[u],tp);
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].to;
if(v==son[u]) continue;
dfs2(v,v);
}
}
int sum1[N*4],sum2[N*4];
void pushup(int rt){
sum1[rt]=sum1[rt<<1]+sum1[rt<<1|1];
if(sum1[rt]>=MOD) sum1[rt]-=MOD;
sum2[rt]=sum2[rt<<1]+sum2[rt<<1|1];
if(sum2[rt]>=MOD) sum2[rt]-=MOD;
}
int pos,num1,num2;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
void update(int l,int r,int rt){
if(l==r){
sum1[rt]+=num1,sum2[rt]+=num2;
if(sum1[rt]>=MOD) sum1[rt]-=MOD;
if(sum2[rt]>=MOD) sum2[rt]-=MOD;
return ;
}
int m=l+r>>1;
if(pos<=m) update(lson);
else update(rson);
pushup(rt);
}
void add(PI &ans,PI tmp){
ans.first+=tmp.first;
if(ans.first>=MOD) ans.first-=MOD;
ans.second+=tmp.second;
if(ans.second>=MOD) ans.second-=MOD;
}
int L,R,n;
PI query(int l,int r,int rt){
if(L<=l&&R>=r) return (PI){sum1[rt],sum2[rt]};
int m=l+r>>1;
PI ans=(PI){0,0};
if(L<=m) add(ans,query(lson));
if(R>m) add(ans,query(rson));
return ans;
}
PI Query(int u,int v){
int f1=top[u],f2=top[v];
PI ans=(PI){0,0};
while(f1!=f2){
if(deep[f1]<deep[f2]) swap(f1,f2),swap(u,v);
L=id[f1],R=id[u];
add(ans,query(1,n,1));
u=fa[f1],f1=top[u];
}
if(deep[u]>deep[v]) swap(u,v);
L=id[u],R=id[v];
add(ans,query(1,n,1));
return ans;
}
int main(){
int x,q,op,u,k;
init();
scanf("%d",&n);
for(int i=2;i<=n;i++){
scanf("%d",&x);
addedge(x,i);
}
dfs1(1,0);
dfs2(1,0);
scanf("%d",&q);
while(q--){
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&u,&x,&k);
num1=(x+1LL*deep[u]*k)%MOD,num2=k,pos=id[u];
//printf("PPPP%d %d %d\n",id[u],num1,num2);
update(1,n,1);
}
else{
scanf("%d",&u);
PI tmp=Query(u,1);
//printf("%d %d\n",tmp.first,tmp.second);
printf("%lld\n",((tmp.first-1LL*tmp.second*deep[u])%MOD+MOD)%MOD);
}
}
return 0;
}