CQBZ_ZJYjoe @ 2024-09-01 11:07:58
我怀疑我写了一个假的长链剖分。
#include<bits/stdc++.h>
#define int long long
#define INT LONG_LONG
#define fast_io ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define lowbit(x) x&-x
using namespace std;
int n,m,r,p,idd[100005],sd[100005],fa[100005],top[100005],son[100005],b[100005],a[100005],siz[100005],tot;
struct Node
{
int d,l,r,tag,siz;
}tree[400005];
vector<signed> edges[100005];
inline void push_data(int x)
{
tree[x*2].d=(tree[x*2].d+tree[x].tag*tree[x*2].siz)%p;
tree[x*2+1].d=(tree[x*2+1].d+tree[x].tag*tree[x*2+1].siz)%p;
tree[x*2].tag=(tree[x*2].tag+tree[x].tag)%p;
tree[x*2+1].tag=(tree[x*2+1].tag+tree[x].tag)%p;
tree[x].tag=0;
}
inline void make_tree(int x,int l,int r)
{
tree[x].l=l,tree[x].r=r,tree[x].siz=r-l+1;
if (l==r)
{
tree[x].d=a[l]%p;
return ;
}
make_tree(x*2,l,(l+r)>>1),make_tree(x*2+1,((l+r)>>1)+1,r);
tree[x].d=(tree[x*2].d+tree[x*2+1].d)%p;
}
inline void change(int x,int l,int r,int k)
{
if (tree[x].l>=l&&tree[x].r<=r)
{
tree[x].d=(tree[x].d+k*tree[x].siz)%p;
tree[x].tag=(tree[x].tag+k)%p;
return ;
}
push_data(x);
int mid=(tree[x].l+tree[x].r)>>1;
if (mid>=l)
change(x*2,l,r,k);
if (mid<r)
change(x*2+1,l,r,k);
tree[x].d=(tree[x*2].d+tree[x*2+1].d)%p;
}
inline int ask(int x,int l,int r)
{
if (tree[x].l>=l&&tree[x].r<=r)
return (tree[x].d)%p;
push_data(x);
int sum=0,mid=(tree[x].l+tree[x].r)>>1;
if (mid>=l)
sum=(sum+ask(x*2,l,r))%p;
if (mid<r)
sum=(sum+ask(x*2+1,l,r))%p;
return sum;
}
inline void tree_change(int x,int y,int k)
{
while (top[x]!=top[y])
{
if (sd[top[x]]<sd[top[y]])
swap(x,y);
change(1,idd[top[x]],idd[x],k);
x=fa[top[x]];
}
if (sd[x]>sd[y])
swap(x,y);
change(1,idd[x],idd[y],k);
}
inline int tree_ask(int x,int y)
{
int sum=0;
while (top[x]!=top[y])
{
if (sd[top[x]]<sd[top[y]])
swap(x,y);
sum=(sum+ask(1,idd[top[x]],idd[x]))%p;
x=fa[top[x]];
}
if (sd[x]>sd[y])
swap(x,y);
sum=(sum+ask(1,idd[x],idd[y]))%p;
return sum;
}
inline void dfs_1(int x,int faa,int sdd)
{
fa[x]=faa;
son[x]=0;
sd[x]=sdd;
siz[x]=1;
int max_son=-1;
for (auto i:edges[x])
{
if (i==faa)
continue;
dfs_1(i,x,sdd+1);
siz[x]+=siz[i];
if(sd[i]>max_son)
son[x]=i,max_son=sd[i];
}
}
inline void dfs_2(int x,int to)
{
top[x]=to;
idd[x]=++tot;
a[idd[x]]=b[x];
if (!son[x])
return ;
dfs_2(son[x],to);
for (auto i:edges[x])
{
if (i==fa[x]||i==son[x])
continue;
dfs_2(i,i);
}
}
signed main()
{
fast_io;
cin>>n>>m>>r>>p;
for (int i=1;i<=n;i++)
cin>>b[i];
for (int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
edges[u].push_back(v),edges[v].push_back(u);
}
dfs_1(r,0,1);
dfs_2(r,r);
make_tree(1,1,n);
for (int i=1;i<=m;i++)
{
int op,x,y,z;
cin>>op;
if (op==1)
{
cin>>x>>y>>z;
tree_change(x,y,z);
}
else if (op==2)
{
cin>>x>>y;
cout<<tree_ask(x,y)<<endl;
}
else if (op==3)
{
cin>>x>>z;
change(1,idd[x],idd[x]+siz[x]-1,z);
}
else
{
cin>>x;
cout<<ask(1,idd[x],idd[x]+siz[x]-1)<<endl;
}
}
return 0;
}
因为他比重链剖分还快0.07s。
但是
请各位大佬帮帮我。
by Union_Find @ 2024-09-01 11:16:42
数据水吧,也不会有什么人写长链剖分,就没有卡了。
by xudongyi1 @ 2024-09-01 11:18:33
我唐了qwq
by CQBZ_ZJYjoe @ 2024-09-01 11:18:41
@xudongyi1 我是用的深度更新啊