求助长链剖分&hack(玄2关)
查看原帖
求助长链剖分&hack(玄2关)
592080
CQBZ_ZJYjoe楼主2024/9/1 11:07

我怀疑我写了一个假的长链剖分。

#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。

但是

请各位大佬帮帮我。

2024/9/1 11:07
加载中...