Mn Zn刚学OI,树剖30pts求助
查看原帖
Mn Zn刚学OI,树剖30pts求助
545037
rczong楼主2022/11/20 18:12

wa7

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e6;
int n,m,root,p;
struct edge{
	int to,nxt;
}e[N];
int head[N],cnt=0,ans,cont=0,siz[N],a[N],tp[N],rec[N],id[N],vis[N],son[N],fa[N],dep[N];
void add(int u,int v){
	e[++cnt].to=v;
	e[cnt].nxt=head[u];
	head[u]=cnt;
}
void dfs1(int u,int ffa){
	siz[u]=1;
	fa[u]=ffa;
	dep[u]=dep[ffa]+1;
	for(int i=head[u];i;i=e[i].nxt){
		int y=e[i].to;
		if(y==ffa)continue;
		dfs1(y,u);
		siz[u]+=siz[y];
		if(siz[y]>siz[son[u]]){
			son[u]=y;
		}
	}
}
void dfs2(int u,int t){
	tp[u]=t;
	id[u]=++cont;
	rec[cont]=u;
	if(!son[u])return;
	dfs2(son[u],t);
	for(int i=head[u];i;i=e[i].nxt){
		int y=e[i].to;
		if(y==fa[u]||y==son[u])continue;
		dfs2(y,y);
	}
}
struct tree{
	int l,r,sum,tag;
}t[N*4];
void updata(int x){
	t[x].sum=(t[x*2].sum+t[x*2+1].sum)%p;
}
void build(int x,int l,int r){
	t[x].l=l;t[x].r=r;
	if(t[x].l==t[x].r){
		t[x].sum=a[rec[l]]%p;    
		return;
	}
	int mid=(l+r)/2;
	build(x*2,l,mid),
	build(x*2+1,mid+1,r);
	updata(x);
}
void down(int x){
	t[x*2].tag+=t[x].tag%p;
	t[x*2+1].tag+=t[x].tag%p;
	t[x*2].sum+=(t[x].tag*(t[x*2].r-t[x*2].l+1))%p;t[x*2].sum%=p;
	t[x*2+1].sum+=(t[x].tag*(t[x*2+1].r-t[x*2+1].l+1))%p;t[x*2+1].sum%=p;
	t[x].tag=0;
}
void list_modify(int x,int l,int r,int k){
	if(t[x].l>r||t[x].r<l)return;
	else if(t[x].l>=l&&t[x].r<=r){
		t[x].sum=(t[x].sum+(t[x].r-t[x].l+1)*k)%p;
		t[x].tag=(t[x].tag+k)%p;
		return;
	}
	down(x);
	list_modify(x*2,l,r,k);
	list_modify(x*2+1,l,r,k);
	updata(x);
}
int list_query(int x,int l,int r){
	if(t[x].l>r||t[x].r<l)return 0;
	else if(t[x].l>=l&&t[x].r<=r)return t[x].sum%p;
	down(x);
	return (list_query(x*2,l,r)%p+list_query(x*2+1,l,r)%p)%p;
}
void tree_updata(int u,int v,int k){
	while(tp[u]!=tp[v]){
		if(dep[tp[u]]<dep[tp[v]])swap(u,v);
		list_modify(1,id[tp[u]],id[u],k);
		u=fa[tp[u]];
	}
	if(dep[u]>dep[v]){
		swap(u,v);
	}
	list_modify(1,id[u],id[v],k);
}
int tree_query(int u,int v){
	ans=0;
	while(tp[u]!=tp[v]){
		if(dep[tp[u]]<dep[tp[v]])swap(u,v);
		ans=(ans+list_query(1,id[tp[u]],id[u]))%p;
		u=fa[tp[u]];
	}
	if(dep[u]>dep[v]){
		swap(u,v);
	}
	ans=(ans+list_query(1,id[u],id[v]))%p;
	return ans%p;
}
void sontree_modify(int x,int z){
	list_modify(1,id[x],id[x]+siz[son[x]],z);
	for(int i=head[x];i;i=e[i].nxt){
		int y=e[i].to;
		if(y==son[x]||y==fa[x])continue;
		sontree_modify(y,z);
	}
}
int sontree_query(int x){
	ans=0;
	if(!son[x])return list_query(1,id[x],id[x])%p;
	ans=(ans+list_query(1,id[x],id[x]+siz[son[x]]))%p;
	ans%=p;
	for(int i=head[x];i;i=e[i].nxt){
		int y=e[i].to;
		if(y==son[x]||y==fa[x])continue;
		ans=(ans+sontree_query(y))%p;
	}
	return ans%p;
}
signed main(){
	//freopen("t1.in","r",stdin);
	//freopen("t1.out","w",stdout);
	cin>>n>>m>>root>>p;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n-1;i++){
		int u,v;
		cin>>u>>v;
		add(u,v);add(v,u);
	}
	dfs1(root,0);dfs2(root,root);
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int op,l,r,x;
		cin>>op;
		if(op==1){
			cin>>l>>r>>x;
			tree_updata(l,r,x);
		}
		else if(op==2){
			cin>>l>>r;
			cout<<tree_query(l,r)%p<<endl;
		}
		else if(op==3){
			cin>>l>>x;
			sontree_modify(l,x);
		}
		else{
			cin>>l;
			cout<<sontree_query(l)%p<<endl;
		}
	}
	//fclose(stdin);
	//fclose(stdout);
	return 0;
} 
2022/11/20 18:12
加载中...