P3384 【模板】重链剖分/树链剖分 非常诡异的82分,求调
  • 板块灌水区
  • 楼主Evan郭
  • 当前回复2
  • 已保存回复2
  • 发布时间2023/8/14 17:50
  • 上次更新2023/11/3 03:49:42
查看原帖
P3384 【模板】重链剖分/树链剖分 非常诡异的82分,求调
549801
Evan郭楼主2023/8/14 17:50
#include<bits/stdc++.h>
using namespace std;
#define long long int;
int mod,d[500005],size[500005],fa[500005],z[500005],n,m,cnt,r,p,w[500005],top[500005],id[500005],nw[500005],lll;
vector<int> tree[500005];
struct data {
	int l;
	int r;
	int sum;
	int lazy;
} t[2000005];
void dfs1(int now,int f) {
	size[now]=1;
	fa[now]=f;
	for(int i=0; i<tree[now].size(); i++) {
		int to=tree[now][i];
		if(to==f) continue;
		fa[to]=now;
		d[to]=d[now]+1;
		dfs1(to,now);
		size[now]+=size[to];
		z[now]=((size[to]>size[z[now]]) ? to : z[now]);
	}
}
void dfs2(int now) {
	id[now]=++cnt;
	nw[cnt]=w[now];
	top[now]=(z[fa[now]]==now) ? top[fa[now]] : now;
	if(!z[now])
		return;
	dfs2(z[now]);
	for(int i=0; i<tree[now].size(); i++) {
		int to=tree[now][i];
		if(to!=fa[now]&&to!=z[now]&&fa[to]!=0)
			dfs2(to);
	}
}
void build(int p,int l,int r) {
	t[p].l=l;
	t[p].r=r;
	if(l==r)
		t[p].sum=nw[l]%mod;
	else {
		int mid=(l+r)>>1;
		build(p*2,l,mid);
		build(p*2+1,mid+1,r);
		t[p].sum=t[p*2].sum+t[p*2+1].sum;
		t[p].sum%=mod;
	}
	return;
}
void add(int l,int r,int num,int p) {
	if(t[p].l>=l&&t[p].r<=r) {
		t[p].sum+=(t[p].r-t[p].l+1)*num;
		t[p].lazy+=num;
		t[p].sum%=mod;
		t[p].lazy%=mod;
		return;
	} else if(t[p].l>r||t[p].r<l)
		return;
	else
		t[p].sum+=(min(t[p].r,r)-max(t[p].l,l)+1)*num;
	if(t[p*2].r>=l)
		add(l,r,num,p*2);
	if(t[p*2+1].l<=r)
		add(l,r,num,p*2+1);
}
int query(int l,int r,int p) {
	int ans=0;
	if(t[p].l>=l&&t[p].r<=r) {
		ans+=t[p].sum;
		ans%=mod;
		return ans;
	} else if(t[p].l>r||t[p].r<l)
		return ans;
	else
		ans=(ans+(min(t[p].r,r)-max(t[p].l,l)+1)*t[p].lazy)%mod;
	if(t[p*2].r>=l)
		ans=(ans+query(l,r,p*2))%mod;
	if(t[p*2+1].l<=r)
		ans=(ans+query(l,r,p*2+1))%mod;
	return ans%mod;
}
void lca_add(int u,int v,int z) {
	while(top[u]!=top[v]) {
		if(d[top[u]]<d[top[v]])
			swap(u,v);
		add(id[top[u]],id[u],z%mod,1);
		u=fa[top[u]];
	}
	if(d[u]>d[v])
		swap(u,v);
	add(id[u],id[v],z%mod,1);
	return;
}
int lca_query(int u,int v) {
	int ans=0;
	while(top[u]!=top[v]) {
		if(d[top[u]]<d[top[v]])
			swap(u,v);
		ans=(ans+query(id[top[u]],id[u],1))%mod;
		u=fa[top[u]];
	}
	if(d[u]>d[v])
		swap(u,v);
	ans=(ans+query(id[u],id[v],1))%mod;
	return ans%mod;
}
signed main() {
//	freopen("1.in","r",stdin);
//	freopen("1.out","w",stdout);
	cin>>n>>m>>r>>mod;
	for(int i=1; i<=n; i++)
		cin>>w[i];
	for(int i=1; i<n; i++) {
		int u,v;
		cin>>u>>v;
		tree[u].push_back(v);
		tree[v].push_back(u);
	}
	dfs1(r,0);
	dfs2(r);
	fa[r]=0;
	build(1,1,n);
	while(m--) {
		int op,x,y,z;
		cin>>op;
		if(op==1) {
			cin>>x>>y>>z;
			lca_add(x,y,z%mod);
		}
		if(op==2) {
			cin>>x>>y;
			cout<<lca_query(x,y)%mod<<'\n';
		}
		if(op==3) {
			cin>>x>>z;
			add(id[x],id[x]+size[x]-1,z%mod,1);
		}
		if(op==4) {
			cin>>x;
			cout<<query(id[x],id[x]+size[x]-1,1)%mod<<'\n';
		}
//		for(int i=1;i<=n;i++)
//			cout<<query(id[i],id[i],1)<<' ';
//		cout<<endl;
	}
	return 0;
}
2023/8/14 17:50
加载中...