看到距离有关可以联想到跟深度有关系,可以用深度表示距离关系。
假设现在有一操作1 v x k,那么对于v下一点u,设dep[v]为v的深度,那么两点间距离就是dep[u]-dep[v],于是u点就会增加\(x-k*(dep[u]-dep[v])=x-k*dep[u]+k*dep[v]\)。
由此来看,只需要把v一下的\(sum1\)都加上\(x-dep[u]\),然后再对u点再查询时单独加回一个\(k*dep[v]\),对于多个操作就加回k的和乘上\(dep[v]\)。
为了维护k的和,可以设\(sum2\),在操作时把v以下的\(sum2\)都加上\(k\)。
对一个子树进行操作,由于只对根操作,故直接dfs序即可。
代码
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
#define maxn 300005
#define ll long long
using namespace std;
int n;
int head[maxn],to[maxn*2],nex[maxn*2],m1;
void add(int u,int v) {
to[++m1]=v;
nex[m1]=head[u];
head[u]=m1;
}
int lf[maxn],rt[maxn],dfn[maxn];
ll dep[maxn],num;
void dfs(int now,int last) {
lf[now]=++num,dfn[num]=now,dep[now]=dep[last]+1;
for(int i=head[now];i;i=nex[i]) {
int st=to[i];
dfs(st,now);
}
rt[now]=num;
}
struct smt {
int l,r;
ll tag1,tag2;
} T[maxn*4];
int ls(int x) {return x<<1;}
int rs(int x) {return x<<1|1;}
ll mod=1e9+7;
void tree_pre(int x,int l,int r) {
T[x].l=l,T[x].r=r;
if(l==r) return;
int mid=(l+r)>>1;
tree_pre(ls(x),l,mid);
tree_pre(rs(x),mid+1,r);
}
void change(int x,ll val1,ll val2) {
T[x].tag1=(T[x].tag1+val1)%mod;
T[x].tag2=(T[x].tag2+val2)%mod;
}
void push_down(int x) {
change(ls(x),T[x].tag1,T[x].tag2);
change(rs(x),T[x].tag1,T[x].tag2);
T[x].tag1=T[x].tag2=0;
}
void modify(int x,int l,int r,ll val1,ll val2) {
if(T[x].l>=l && T[x].r<=r) {
change(x,val1,val2);
return;
}
push_down(x);
if(T[ls(x)].r>=l) modify(ls(x),l,r,val1,val2);
if(T[rs(x)].l<=r) modify(rs(x),l,r,val1,val2);
}
ll query(int x,int l,int r) {
if(T[x].l>=l && T[x].r<=r) return (T[x].tag1-dep[dfn[l]]*T[x].tag2%mod+mod)%mod;
push_down(x);
if(T[ls(x)].r>=l) return query(ls(x),l,r);
if(T[rs(x)].l<=r) return query(rs(x),l,r);
}
int main() {
// freopen("CF396C.in","r",stdin);
// freopen("CF396C.out","w",stdout);
scanf("%d",&n);
for(int i=2;i<=n;i++) {
int x; scanf("%d",&x);
add(x,i);
}
dfs(1,0);
tree_pre(1,1,n);
int q; scanf("%d",&q);
for(int i=1;i<=q;i++) {
int t;
ll v,x,k;
scanf("%d",&t);
if(t==1) {
scanf("%lld%lld%lld",&v,&x,&k);
ll val1=(x+dep[v]*k%mod)%mod,val2=k;
modify(1,lf[v],rt[v],val1,val2);
}
else {
scanf("%lld",&v);
printf("%lld\n",query(1,lf[v],lf[v]));
}
}
return 0;
}
标签:tag1,int,ll,Tree,dep,maxn,CF396C,Changing,now
From: https://www.cnblogs.com/1n87/p/18018603