社区讨论

帮帮弱小而无助的南瓜吧QAQ

P3384【模板】重链剖分 / 树链剖分参与者 4已保存回复 8

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
8 条
当前快照
1 份
快照标识符
@mi6w9yvl
此快照首次捕获于
2025/11/20 11:51
4 个月前
此快照最后确认于
2025/11/20 11:51
4 个月前
查看原帖
1,3,4,8ac,9wa,其他全t了是为什么呀qwq 悄悄咪咪问一句,用不用开ll啊orz
CPP
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#define maxn 200010
#define maxm 400010
using namespace std;

int n,m,root,plane,u,v,x,y,z,cnt,tot,top,num,opt;
int fir[maxn],val[maxn],dfn[maxn],dep[maxn];
int fa[maxn],sz[maxn],wson[maxn],node[maxn],head[maxn];
int ll[maxn<<1],rr[maxn<<1],w[maxn<<1],tag[maxn<<1];

struct qwq
{
	int to,nxt;
}e[maxm];

int read()
{
	int xx=0,kk=1;char ch=' ';
	while(!isdigit(ch)){ch=getchar();if(ch=='-')kk=-1;}
	while(isdigit(ch)){xx=xx*10+ch-'0';ch=getchar();}
	return kk*xx;
}

void addedge(int u,int v)
{
	e[++num].to=v;
	e[num].nxt=fir[u];
	fir[u]=num;
}

void build(int l,int r,int num)
{
	ll[num]=l,rr[num]=r;
	if(l==r){w[num]=val[node[l]];return;}
	int mid=(l+r)>>1;
	build(l,mid,num<<1);
	build(mid+1,r,num<<1|1);
	w[num]=(w[num<<1]+w[num<<1|1])%plane;
}

void pushdown(int num)
{
	w[num<<1]=(w[num<<1]+(rr[num<<1]-ll[num<<1]+1)*tag[num])%plane;
	w[num<<1|1]=(w[num<<1|1]+(rr[num<<1|1]-ll[num<<1|1]+1)*tag[num])%plane;
	tag[num<<1]=(tag[num<<1]+tag[num])%plane;
	tag[num<<1|1]=(tag[num<<1|1]+tag[num])%plane;
	tag[num]=0;
}

void add(int l,int r,int num,int k)
{
	if(l>rr[num]||r<ll[num]) return;
	if(l<=ll[num]&&r>=rr[num])
	{
	    tag[num]=(tag[num]+k)%plane;
		w[num]=(w[num]+(rr[num]-ll[num]+1)*k)%plane;
		return;
	}
	pushdown(num);
	add(l,r,num<<1,k);
	add(l,r,num<<1|1,k);
	w[num]=(w[num<<1]+w[num<<1|1])%plane;
}

int query(int l,int r,int num)
{
	if(l>rr[num]||r<ll[num]) return 0;
	if(l<=ll[num]&&r>=rr[num]) return w[num];
	pushdown(num);
	return (query(l,r,num<<1)+query(l,r,num<<1|1))%plane; 
}

void dfs1(int u,int f)
{
	fa[u]=f;sz[u]=1;
	dep[u]=dep[f]+1;
	for(int i=fir[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==fa[u]) continue;
		dfs1(v,u);
		sz[u]+=sz[v];
		if(sz[v]>sz[wson[u]]) wson[u]=v;
	}
}

void dfs2(int u,int top)
{
	dfn[u]=++tot,node[tot]=u,head[u]=top;
	if(wson[u]) dfs2(wson[u],top);
	for(int i=fir[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v!=fa[u]&&v!=wson[u]) dfs2(v,v);
	}
}

void update(int x,int y,int z)
{
	while(head[x]!=head[y])
	{
		if(dfn[head[x]]<dfn[head[y]]) swap(x,y);
		add(dfn[head[x]],dfn[x],1,z),x=fa[head[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	add(dfn[x],dfn[y],1,z);
}

int getsum(int x,int y)
{
	int ans=0;
	while(head[x]!=head[y])
	{
		if(dfn[head[x]]<dfn[head[y]]) swap(x,y);
		ans=(ans+query(dfn[head[x]],dfn[x],1))%plane;
		x=fa[head[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	ans=(ans+query(dfn[x],dfn[y],1))%plane;
	return ans;
}

int main()
{
	n=read(),m=read(),root=read(),plane=read();
	for(int i=1;i<=n;++i)
		val[i]=read()%plane;
	for(int i=1;i<n;++i)
	{
		u=read(),v=read();
		addedge(u,v),addedge(v,u);
	}
	dfs1(root,0),dfs2(root,1),build(1,n,1);
	for(int i=1;i<=m;++i)
	{
		switch(opt=read())
		{
			case 1:{x=read(),y=read(),z=read()%plane;update(x,y,z);break;}
			case 2:{x=read(),y=read();printf("%d\n",getsum(x,y));break;}
			case 3:{x=read(),z=read()%plane;add(dfn[x],dfn[x]+sz[x]-1,1,z);break;}
			case 4:{x=read();printf("%d\n",query(dfn[x],dfn[x]+sz[x]-1,1));break;}
		}
	}
	return 0;
}

回复

8 条回复,欢迎继续交流。

正在加载回复...