求助轻重链剖分模板
  • 板块学术版
  • 楼主LoverBoyInMacau
  • 当前回复7
  • 已保存回复7
  • 发布时间2020/7/30 15:06
  • 上次更新2023/11/6 21:46:34
查看原帖
求助轻重链剖分模板
262074
LoverBoyInMacau楼主2020/7/30 15:06

RT

#include<bits/stdc++.h>
using namespace std;
#define re register
#define il inline
#define ll long long
const int maxsize=400010;

ll s,mod,tot,num,n,m;
ll head[maxsize],dep[maxsize],sum[maxsize],a[maxsize],lazy[maxsize],fa[maxsize],son[maxsize],dfn[maxsize],ch[maxsize],top[maxsize],size[maxsize];

il ll read()
{
    ll x=0,w=0;
    char ch=0;
    while(!isdigit(ch))
    {
        w|=ch=='-';
        ch=getchar();
    }
    while(isdigit(ch))
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return w?-x:x;
}

il void write(ll x)
{
    if(x>9)
        write(x/10);
    if(x<0)
    {
        x=-x;
        putchar('-');
    }
    putchar(x%10+'0');
}

struct edge
{
    ll to,nxt;
} e[maxsize];

il void add(int u,int v)
{
	e[num++].to=v;
	e[num].nxt=head[u];
	head[u]=num;
}

//   线段树↓ 

il void build(int x,int l,int r)
{
    if(l==r)  {sum[x]=a[l];return;}
    int mid=(l+r)>>1;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
    sum[x]=sum[x<<1]+sum[x<<1|1];
    sum[x]%=mod;
    return;
}

il void down(int x,int l,int r)//标记下放 
{
	int mid=(l+r)>>1;
	lazy[x<<1]+=lazy[x];
	lazy[x<<1]%=mod;
	lazy[x<<1|1]+=lazy[x];
	lazy[x<<1|1]%=mod;
	sum[x<<1]+=lazy[x]*(mid+1-l);
	sum[x<<1]%=mod;
	sum[x<<1|1]+=lazy[x]*(r-mid);
	sum[x<<1|1]%=mod;
	lazy[x]=0;
	return;
}

il void change(int x,int lnow,int rnow,int lwant,int rwant,ll addnum)//区间每个数都加addnum 
{
	if(lwant<=lnow&&rwant>=rnow){sum[x]+=addnum*(rnow-lnow+1);sum[x]%=mod;lazy[x]+=addnum;lazy[x]%=mod;return;}
	if(lnow>rwant||rnow<lwant)return;
	int mid=(lnow+rnow)>>1;
	if(lazy[x])  down(x,lnow,rnow);
	if(mid>=lwant)change(x<<1,lnow,mid,lwant,rwant,addnum); 
	if(mid<rwant)change(x<<1|1,mid+1,rnow,lwant,rwant,addnum);
	sum[x]=(sum[x<<1]+sum[x<<1|1])%mod;
	return;
}


il ll ask(int x,int lnow,int rnow,int lwant,int rwant)
{
	if(lwant<=lnow&&rwant>=rnow)  return sum[x]%mod;
	if(lwant>rnow||rwant<lnow)  return 0;
	int mid=(lnow+rnow)>>1;
	if(lazy[x])  down(x,lnow,rnow);
	ll leftans=0,rightans=0;
	if(mid>=lwant)leftans=ask(x<<1,lnow,mid,lwant,rwant); 
	if(mid<rwant)rightans=ask(x<<1|1,mid+1,rnow,lwant,rwant);
	return (leftans%mod+rightans%mod)%mod;
}

//////////////////////////////////////////////////////////

il void dfs1(int x)//求某节点子树大小+轻重儿子
{
    size[x]=1;
    for(re int i=head[x]; i; i=e[i].nxt)
    {
        int v=e[i].to;
        if(!dep[v])//OR if(v!=fa[x])
        {
            dep[v]=dep[x]+1;//向下 深度+1
            fa[v]=x;
            dfs1(v);
            size[x]+=size[v];//更新长度
            if(size[v]>size[son[x]])	son[x]=v;//求重儿子
        }
    }
}

il void dfs2(int x,int xtop)//求DFS序
{
//l[]表示这个点的dfs序
//然后a[]是以dfs序为下标(维护链)的当前点的点值
//ch[]是题目给出的点值
//top[]记录的是这个点所在的链的顶端的那个点,用来跳lca
	dfn[x]=++tot;
	a[tot]=ch[x];
	top[x]=xtop;
	if(son[x])	dfs2(son[x],xtop);
	for(re int i=head[x];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v!=fa[x]&&v!=son[x])	dfs2(v,v);
	}
	return;
}

il ll getedgesum(int x,int y)//查询路径上所有节点值的和  操作2 
{
	ll sum=0;
	int fx=top[x],fy=top[y];
	while(fx!=fy)
	{
		if(dep[fx]<dep[fy])  swap(x,y),swap(fx,fy);
		sum+=ask(1,1,tot,dfn[fx],dfn[fy]);
		x=fa[fx],fx=top[x];//跳一跳 
	}
	if(dfn[x]>dfn[y])  swap(x,y);
	sum+=ask(1,1,tot,dfn[x],dfn[y]);
	return sum;
}

il void addedgesum(int x,int y,int addnum)//在路径上每个点的值都加addnum  操作1 
{
	int fx=top[x],fy=top[y];
	while(fx!=fy)
	{
		if(dep[fx]<dep[fy])  swap(x,y),swap(fx,fy);
		change(1,1,tot,dfn[fx],dfn[x],addnum);
		x=fa[fx],fx=top[x];
	}
	if(dfn[x]>dfn[y])  swap(x,y);
	change(1,1,tot,dfn[x],dfn[y],addnum);
}

int main()
{
	n=read();m=read();s=read();mod=read();
	for(re int i=1;i<=n;i++)  ch[i]=read(),ch[i]%=mod;
	for(re int i=1;i<n;i++)
	{
		int u=read(),v=read();
		add(u,v);add(v,u);
	}
	dep[s]=1;fa[s]=0;
	dfs1(s);dfs2(s,s);build(1,1,n);
	for(re int i=1;i<=m;i++)
	{
		int op=read();
		if(op==1){int u=read(),v=read(),w=read();addedgesum(u,v,w%mod);}
		if(op==2){int u=read(),v=read();write(getedgesum(u,v));puts("");}
		if(op==3){int x=read(),w=read();change(1,1,n,dfn[x],dfn[x]+size[x]-1,w);}
		if(op==4){int x=read();write(ask(1,1,n,dfn[x],dfn[x]+size[x]-1)%mod);puts("");}
	}
	return 0;
}
2020/7/30 15:06
加载中...