树链剖分只AC#11玄一关(附带思路)
查看原帖
树链剖分只AC#11玄一关(附带思路)
1039274
Cypher_404楼主2024/10/5 21:32

我说下我的思路:

将边 ABA\to B

变成 aC+CBa\to C+ C\to B

ABA\to B 的边权转换为 CC 的点权。

然后就是树链剖分的板子了。

玄一关,感谢 dalao。

//#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define int long long
template< typename T > inline void read(T &x)
{
    char c=getchar();x=0;int f=0;
    for(;!isdigit(c);c=getchar()) f|=(c=='-');
    for(;isdigit(c);c=getchar()) x=((x<<3)+(x<<1)+(c^48));
    x=f?-x:x;
}
const int N=800080;
int tot,head[N],n,m,a[N],cnt,dfn[N],top[N],siz[N],son[N],dep[N],fa[N],w[N];
struct edge
{
	int v,net;
}e[N<<2];
void addedge(int u,int v)
{
	tot++;
	e[tot].v=v;
	e[tot].net=head[u];
	head[u]=tot;
}
void dfs1(int u,int f)
{
	fa[u]=f;
	siz[u]=1;
	dep[u]=dep[f]+1;
	for(int i=head[u];i;i=e[i].net)
	{
		if(e[i].v!=f)
		{
			dfs1(e[i].v,u);
		}
		else
		continue;
		siz[u]+=siz[e[i].v];
		if(siz[e[i].v]>siz[son[u]])
		{
			son[u]=e[i].v;
		}
	}
}
void dfs2(int u,int f,int tp)
{
	cnt++;
	dfn[u]=cnt;
	top[u]=tp;
	if(son[u])dfs2(son[u],u,tp);
	for(int i=head[u];i;i=e[i].net)
	{
		if(e[i].v==f||e[i].v==son[u])
		{
			continue;
		}
		dfs2(e[i].v,u,e[i].v);
	}
}
#define mid ((l+r)>>1)
long long bian[N<<2],cha[N<<2],maxn[N<<2],minn[N<<2];
void pushup(int k)
{
	bian[k]=    bian[k<<1]+bian[k<<1|1];
	maxn[k]=max(maxn[k<<1],maxn[k<<1|1]);
	minn[k]=min(minn[k<<1],minn[k<<1|1]);
}
void build(int k,int l,int r)
{
	if(l==r)
	{
		bian[k]=maxn[k]=minn[k]=w[l];
		if(w[l]==LONG_LONG_MIN)
		{
			bian[k]=0;
			maxn[k]=LONG_LONG_MIN;
			minn[k]=LONG_LONG_MAX;
		}
		return;
	}
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	pushup(k);
}
void CHA(int k,int l,int r)
{
	bian[k]=-bian[k];
	int t=maxn[k];
	maxn[k]=-minn[k];
	minn[k]=-t;
}
void pushdown(int k,int l,int r)
{
	if(cha[k]!=0)
	{
		cha[k<<1]^=1;
		CHA(k<<1,l,mid);
		cha[k<<1|1]^=1;
		CHA(k<<1|1,mid+1,r);
		cha[k]=0;
	}
}
void modifycov(int k,int l,int r,int x,long long v)
{
	if(l==r)
	{
		bian[k]=maxn[k]=minn[k]=v;
//		cha[k]=0;
		return;
	}
	pushdown(k,l,r);
	if(x<=mid)
	{
		modifycov(k<<1,l,mid,x,v);
	}
	else
	{
		modifycov(k<<1|1,mid+1,r,x,v);
	}
	pushup(k);
}
void modifycha(int k,int l,int r,int x,int y)
{
	if(x<=l&&r<=y)
	{
		CHA(k,l,r);
		return;
	}
	pushdown(k,l,r);
	if(x<=mid)
	{
		modifycha(k<<1,l,mid,x,y);
	}
	if(y>mid)
	{
		modifycha(k<<1|1,mid+1,r,x,y);
	}
	pushup(k);
}
long long querysum(int k,int l,int r,int x,int y)
{
	if(x<=l&&r<=y)
	{
		return bian[k];
	}
	pushdown(k,l,r);
	long long ans=0;
	if(x<=mid)
	{
		ans=querysum(k<<1,l,mid,x,y);
	}
	if(y>mid)
	{
		ans+=querysum(k<<1|1,mid+1,r,x,y);
	}
	return ans;
}
long long querymax(int k,int l,int r,int x,int y)
{
	if(x<=l&&r<=y)
	{
		return maxn[k];
	}
	pushdown(k,l,r);
	long long ans=LONG_LONG_MIN;
	if(x<=mid)
	{
		ans=querymax(k<<1,l,mid,x,y);
	}
	if(y>mid)
	{
		ans=max(ans,querymax(k<<1|1,mid+1,r,x,y));
	}
	return ans;
}
long long querymin(int k,int l,int r,int x,int y)
{
	if(x<=l&&r<=y)
	{
		return minn[k];
	}
	pushdown(k,l,r);
	long long ans=LONG_LONG_MAX;
	if(x<=mid)
	{
		ans=querymin(k<<1,l,mid,x,y);
	}
	if(y>mid)
	{
		ans=min(ans,querymin(k<<1|1,mid+1,r,x,y));
	}
	return ans;
}
long long anssum(int x,int y)
{
	long long ans=0;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])
		{
			swap(x,y);
		}
		ans+=querysum(1,1,n,dfn[top[x]],dfn[x]);
		x=fa[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	ans+=querysum(1,1,n,dfn[x],dfn[y]);
	return ans;
}
long long ansmax(int x,int y)
{
	long long ans=LONG_LONG_MIN;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])
		{
			swap(x,y);
		}
		int t=querymax(1,1,n,dfn[top[x]],dfn[x]);
		if(t!=LONG_LONG_MAX)
		{
			ans=max(t,ans);
		}
		x=fa[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	int t=querymax(1,1,n,dfn[x],dfn[y]);
	if(t!=LONG_LONG_MAX)
	{
		ans=max(t,ans);
	}
	return ans;
}
long long ansmin(int x,int y)
{
	long long ans=LONG_LONG_MAX;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])
		{
			swap(x,y);
		}
		int t=querymin(1,1,n,dfn[top[x]],dfn[x]);
		if(t!=LONG_LONG_MIN)
		{
			ans=min(t,ans);
		}
		x=fa[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	int t=querymin(1,1,n,dfn[x],dfn[y]);
	if(t!=LONG_LONG_MIN)
	{
		ans=min(t,ans);
	}
	return ans;
}
signed main()
{
//	freopen("P1505_1.in","r",stdin);
//	freopen("fk.out","w",stdout);
	for(int i=1;i<=800050;i++)
	{
		a[i]=w[i]=LONG_LONG_MIN;
	}
	read(n);
	for(int i=1;i<n;i++)
	{
		int x,y,z;
		read(x);
		read(y);
		x++;
		y++;
		read(z);
		addedge(x,i+n);
		addedge(i+n,y);
		addedge(y,i+n);
		addedge(i+n,x);
		a[i+n]=z;
	}
	dfs1(1,0);
	dfs2(1,0,1);
	int fk=n;
	n*=4;
	n+=3;
	for(int i=1;i<=n;i++)
	{
		w[dfn[i]]=a[i];
	}
	build(1,1,n);
	read(m);
	while(m--)
	{
		string opt;
		int x,y;
		cin>>opt;
		read(x);
		read(y);
		if(opt=="C")
		{
			modifycov(1,1,n,dfn[x+fk],y);
//			cout<<"C";
			continue;
		}
		if(opt=="N")
		{
			x++;
			y++;
//			if(x==y)
//			{
//				continue;
//			}
//			cout<<x<<' '<<y<<'\n';
			modifycha(1,1,n,dfn[x],dfn[y]);
//			cout<<"N";
			continue;
		}
		if(x==y)
		{
			cout<<0<<'\n';
			continue;
		}
		if(opt=="SUM")
		{
			x++;
			y++;
//			cout<<1<<' ';
			cout<<anssum(x,y)<<'\n';
			continue;
		}
		if(opt=="MAX")
		{
			x++;
			y++;
//			cout<<2<<' ';
			cout<<ansmax(x,y)<<'\n';
			continue;
		}
		if(opt=="MIN")
		{
			x++;
			y++;
//			cout<<3<<' ';
			cout<<ansmin(x,y)<<'\n';
			continue;
		}
	}
	return 0;
}
2024/10/5 21:32
加载中...