CF396C On Changing Tree

看到距离有关可以联想到跟深度有关系,可以用深度表示距离关系。
假设现在有一操作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;
}
posted @ 2024-02-17 23:08  Ian8877  阅读(14)  评论(0)    收藏  举报