萌新刚学树剖,样例没过求调
查看原帖
萌新刚学树剖,样例没过求调
1384158
Alvin0228楼主2024/8/24 16:37
#include<bits/stdc++.h>
using namespace std;
int n,m,r,p;
int w[100005];
int dep[100005],fa[100005],son[100005],siz[100005];
int id[100005],wt[100005],top[100005],cnt;
//-----------存图------------- 
int head[500005],num_edge;
struct Edge
{
	int nxt,to;
}edge[500005];
void add_edge (int from,int to)
{
	edge[++num_edge].nxt=head[from];
	edge[num_edge].to=to;
	head[from]=num_edge;
}
//------------segtree---------
struct node
{
	int val,addmark;
}segtree[400005];
void build(int root,int start,int end)
{
	segtree[root].addmark=0;
	if (start==end) segtree[root].val=wt[start]%p;
	else
	{
		int mid=(start+end)/2;
		build(root*2,start,mid);
		build(root*2+1,mid+1,end);
		segtree[root].val=segtree[root*2].val+segtree[root*2+1].val;
		segtree[root].val%=p;
	}
}
void pushdown(int root,int l1,int r1,int l2,int r2)
{
	if (segtree[root].addmark!=0)
	{
		segtree[root*2].addmark+=segtree[root].addmark;
		segtree[root*2+1].addmark+=segtree[root].addmark;
		segtree[root*2].val+=segtree[root].addmark*(r1-l1+1);
		segtree[root*2].val%=p;
		segtree[root*2+1].val+=segtree[root].addmark*(r2-l2+1);
		segtree[root*2+1].val%=p;
		segtree[root].addmark=0;
	}
}
int query(int root,int nstart,int nend,int qstart,int qend)
{
	if (qstart>nend||qend<nstart) return 0;
	if (qstart<=nstart&&qend>=nend) 
	{
		segtree[root].val%=p;
		return segtree[root].val;
	}
	int mid=(nstart+nend)/2;
	pushdown(root,nstart,mid,mid+1,nend);
	return (query(root*2,nstart,mid,qstart,qend)+
		    query(root*2+1,mid+1,nend,qstart,qend))%p;
}
void update(int root,int nstart,int nend,int ustart,int uend,int addval)
{
	if (ustart>nend||uend<nstart) return ;
	if (ustart<=nstart&&uend>=nend)
	{
		segtree[root].addmark+=addval;
		segtree[root].val+=addval*(nend-nstart+1);
		return ;
	}
	int mid=(nstart+nend)/2;
	pushdown(root,nstart,mid,mid+1,nend);
	if (ustart<mid) update(root*2,nstart,mid,ustart,uend,addval);
	if (uend>mid) update(root*2+1,mid+1,nend,ustart,uend,addval);
	segtree[root].val=(segtree[root*2].val+segtree[root*2+1].val)%p; 
}
//------------question--------
int query1(int x,int y)
{
	int ans=0;
	while (top[x]!=top[y])
	{
		if (dep[top[x]]<dep[top[y]]) swap(x,y);
		ans+=query(1,1,n,id[top[x]],id[x]);
		ans%=p;
		x=fa[top[x]];//change a lian
	}
	if (dep[x]>dep[y]) swap(x,y);
	ans+=query(1,1,n,id[x],id[y]);
	ans%=p;
	return ans;
}
void update1(int x,int y,int k)
{
	k%=p;
	while (top[x]!=top[y])
	{
		if (dep[top[x]]<dep[top[y]]) swap(x,y);
		update(1,1,n,id[top[x]],id[x],k);
		x=fa[top[x]];//change a lian
	}
	if (dep[x]>dep[y]) swap(x,y);
	update(1,1,n,id[x],id[y],k);
}
//------------dfs1&2----------
void dfs1(int x,int f,int deep)
{
	dep[x]=deep;
	fa[x]=f;
	siz[x]=1;
	int maxn=-1;//heavy son's son-number
	for (int i=head[x];i;i=edge[i].nxt)
	{
		int y=edge[i].to;
		if (y==f) continue;
		dfs1(y,x,deep+1);
		siz[x]+=siz[y];
		if (siz[y]>maxn) 
		{
			maxn=siz[y];
			son[x]=y;
		}
	}
}
void dfs2(int x,int topl)
{
	cnt++;
	id[x]=cnt;
	wt[cnt]=w[x];
	top[x]=topl;
	if (!son[x]) return ;
	dfs2(son[x],topl);
	for (int i=head[x];i;i=edge[i].nxt)
	{
		int y=edge[i].to;
		if (y==fa[x]||y==son[x]) continue;
		dfs2(y,y);
	}
}
int main ()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cin>>n>>m>>r>>p;
	for (int i=1;i<=n;i++)
	{
		cin>>w[i];
	}
	for (int i=1;i<=n-1;i++)
	{
		int u,v;
		cin>>u>>v;
		add_edge(u,v);
		add_edge(v,u);
	}
	dfs1(r,0,1);
	dfs2(r,r);
	build(1,1,n);
	for (int i=1;i<=m;i++)
	{
		int op;
		cin>>op;
		if (op==1)
		{
			int x,y,k;
			cin>>x>>y>>k;
			update1(x,y,k);
		}
		if (op==2)
		{
			int x,y;
			cin>>x>>y;
			cout<<query1(x,y)<<endl;
		}
		if (op==3)
		{
			int x,k;
			cin>>x>>k;
			update(1,1,n,id[x],id[x]+siz[x]-1,k);
		}
		if (op==4)
		{
			int x;
			cin>>x;
			cout<<query(1,1,n,id[x],id[x]+siz[x]-1)<<endl;
		}
	}
	return 0;
}

2024/8/24 16:37
加载中...