nr0628 @ 2023-07-28 11:46:34
空间都开
(
代码如下:
#include<bits/stdc++.h>
#define int long long
using namespace std;
#define re register
#define brk break
#define rtn return
#define nxtper next_permutation
#define preper prev_permutation
#define eb emplace_back
#define pb eb
#define ins insert
#define rep(i,a,b) for(re int i(a);i<=b;++i)
#define req(i,a,b) for(re int i(a);i>=b;--i)
#define readf(s) freopen(s,"r",stdin)
#define writef(s) freopen(s,"w",stdout)
inline int read()
{
re int x=0; re bool f=1; re char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:f,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?x:-x;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+48);
}
int n,m,rt,mod,head[400001],nxt[400001],to[400001],cnt;
void add_undirected_edge(int x,int y)
{
nxt[++cnt]=head[x];
to[cnt]=y;
head[x]=cnt;
nxt[++cnt]=head[y];
to[cnt]=x;
head[y]=cnt;
}
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
int w[200001],wew[200001];
namespace segtree
{
int tree[200001],tag[200001];
void add_tag(int p,int pl,int pr,int d)
{
tag[p]+=d;
(tree[p]+=d*(pr-pl+1))%=mod;
}
void pushup(int p)
{
(tree[p]=tree[ls(p)]+tree[rs(p)])%=mod;
}
void pushdown(int p,int pl,int pr)
{
if(tag[p])
{
int mid=pl+pr>>1;
add_tag(ls(p),pl,mid,tag[p]);
add_tag(rs(p),mid+1,pr,tag[p]);
tag[p]=0;
}
}
void build(int p,int pl,int pr)
{
tag[p]=0;
if(pl==pr){(tree[p]=wew[pl])%=mod; rtn;}
int mid=pl+pr>>1;
build(ls(p),pl,mid);
build(rs(p),mid+1,pr);
pushup(p);
}
void update(int l,int r,int p,int pl,int pr,int d)
{
if(l<=pl&&pr<=r)
{
add_tag(p,pl,pr,d);
rtn;
}
pushdown(p,pl,pr);
int mid=pl+pr>>1;
if(l<=mid) update(l,r,ls(p),pl,mid,d);
if(r>mid) update(l,r,rs(p),mid+1,pr,d);
pushup(p);
}
int query(int l,int r,int p,int pl,int pr)
{
if(pl>=l&&r>=pr) return tree[p]%=mod;
pushdown(p,pl,pr);
int mid=pl+pr>>1,ans=0;
if(l<=mid) (ans+=query(l,r,ls(p),pl,mid))%=mod;
if(r>mid) (ans+=query(l,r,rs(p),mid+1,pr))%=mod;
return ans%=mod;
}
}
namespace dividedtree
{
int num,father[200001],son[200001],depth[200001],siz[200001],top[200001],id[200001];
void dfs1(int x,int fa)
{
depth[x]=depth[fa]+1;
father[x]=fa;
siz[x]=1;
for(int i=head[x];i;i=nxt[i])
if(to[i]!=fa)
{
father[to[i]]=x;
dfs1(to[i],x);
siz[x]+=siz[to[i]];
if(!son[x]||siz[son[x]]<siz[to[i]]) son[x]=to[i];
}
}
void dfs2(int x,int tx)
{
id[x]=++num;
wew[num]=w[x];
top[x]=tx;
if(!son[x]) rtn;
dfs2(son[x],tx);
for(int i=head[x];i;i=nxt[i])
if(to[i]!=father[x]&&to[i]!=son[x]) dfs2(to[i],to[i]);
}
void update1(int x,int y,int z)
{
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
segtree::update(id[top[x]],id[x],1,1,n,z);
x=father[top[x]];
}
if(depth[x]>depth[y]) swap(x,y);
segtree::update(id[x],id[y],1,1,n,z);
}
int query1(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
(ans+=segtree::query(id[top[x]],id[x],1,1,n))%=mod;
x=father[top[x]];
}
if(depth[x]>depth[y]) swap(x,y);
(ans+=segtree::query(id[x],id[y],1,1,n))%=mod;
return ans;
}
void update2(int x,int k)
{
segtree::update(id[x],id[x]+siz[x]-1,1,1,n,k);
}
int query2(int x)
{
return segtree::query(id[x],id[x]+siz[x]-1,1,1,n)%mod;
}
}
signed main()
{
cin>>n>>m>>rt>>mod;
rep(i,1,n)cin>>w[i];
rep(i,1,n-1) add_undirected_edge(read(),read());
dividedtree::dfs1(rt,0);dividedtree::dfs2(rt,rt);
segtree::build(1,1,n);
int opt,x,y,z;
rep(i,1,m)
{
cin>>opt>>x;
switch(opt)
{
case 1:cin>>y>>z;dividedtree::update1(x,y,z);brk;
case 2:cin>>y;cout<<dividedtree::query1(x,y)<<"\n";brk;
case 3:cin>>y;dividedtree::update2(x,y);brk;
case 4:cout<<dividedtree::query2(x)<<"\n";brk;
}
}
return 0;
}
by nr0628 @ 2023-07-28 12:06:09
找到了,线段树忘开
by Genshineer @ 2023-07-28 12:09:37
@nr0628 线段树要开4倍...
要开到