Codeforces - On Changing Tree

题目链接:Codeforces - On Changing Tree


子树操作,比较显然的dfs序。
我们看一下子树根对其他点的影响或贡献:x-(dep[v]-dep[u])*k
然后拆开:x-dep[v]*k+dep[u]*k
当我们操作根的时候,只要根定了,那么dep[u]*k就是一个定值。看成x的一部分。
所以我们用两个lazy维护x和k即可。

AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10,mod=1e9+7;
int n,q,st[N],ed[N],cnt,dep[N],dfn[N];
vector<int> g[N];
void dfs(int x,int fa){
	st[x]=++cnt; dfn[cnt]=x; dep[x]=dep[fa]+1;
	for(auto to:g[x])	if(to!=x)	dfs(to,x);
	ed[x]=cnt;
}
int ls[N<<2],lk[N<<2];
inline void push_down(int p){
	ls[p<<1]=(ls[p<<1]+ls[p])%mod,ls[p<<1|1]=(ls[p<<1|1]+ls[p])%mod;
	lk[p<<1]=(lk[p<<1]+lk[p])%mod,lk[p<<1|1]=(lk[p<<1|1]+lk[p])%mod;
	ls[p]=lk[p]=0;
}
void change(int p,int l,int r,int ql,int qr,int k,int s){
	if(l==ql&&r==qr){
		ls[p]=(ls[p]+s)%mod;	lk[p]=(lk[p]+k)%mod;	return ;
	}
	int mid=l+r>>1;	push_down(p);
	if(qr<=mid)	change(p<<1,l,mid,ql,qr,k,s);
	else if(ql>mid)	change(p<<1|1,mid+1,r,ql,qr,k,s);
	else change(p<<1,l,mid,ql,mid,k,s),change(p<<1|1,mid+1,r,mid+1,qr,k,s);
}
int ask(int p,int l,int r,int x){
	if(l==r)	return (ls[p]-dep[dfn[l]]*lk[p]%mod+mod)%mod;
	int mid=l+r>>1;	push_down(p);
	if(x<=mid)	return ask(p<<1,l,mid,x);
	else	return ask(p<<1|1,mid+1,r,x);
}
signed main(){
	ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
	cin>>n;
	for(int i=2,x;i<=n;i++)	cin>>x,g[x].push_back(i);
	dfs(1,1);	cin>>q;
	for(int i=1,op,v,x,k;i<=q;i++){
		cin>>op>>v;
		if(op==1)	cin>>x>>k,change(1,1,n,st[v],ed[v],k,x+dep[v]*k);
		else	cout<<ask(1,1,n,st[v])<<'\n';
	}
	return 0;
}
发布了553 篇原创文章 · 获赞 242 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/104221012