[旧文章补档]LCT 维护动态生成树*3

本文深入探讨了LCT树在处理最小生成树问题中的应用,通过具体实例展示了如何利用LCT树进行边的增删操作,以及如何在动态变化的图中寻找最小生成树。文章涵盖了BZOJ2594、BZOJ3669和BZOJ3514等题目的解决方案,详细解释了LCT树的维护、查询和更新过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

##BZOJ 2594 [Wc2006]水管局长数据加强版
倒着看 删边就成了加边
加边时若在当前的树上成环 并且这条边的边权<环上最大边权 则删去环上边权最大的边 连上新加入的边
lct维护下这棵树
边权可以拆成点权来处理 例如u->v w 可以拆成 u->t t->v t的点权为w

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define ls ch[o][0]
#define rs ch[o][1]
#define M 1000005
#define INF 1000000000
#define MAXN (100005+1000005)
#define N 100005
using namespace std;
int read()
{
	int t=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
	return t*f;
}
int n,m,q;
int w[MAXN],mx[MAXN],ch[MAXN][2],fa[MAXN],s[MAXN];
bool rev[MAXN];
vector<int> ans;
bool is_root(int o)
{
	return (ch[fa[o]][0]!=o)&&(ch[fa[o]][1]!=o);
}
void pushup(int o)
{
	mx[o]=o;
	if(ls&&w[mx[ls]]>w[mx[o]]) mx[o]=mx[ls];
	if(rs&&w[mx[rs]]>w[mx[o]]) mx[o]=mx[rs]; 
}
void reverse(int o)
{
	rev[o]^=1;
	swap(ls,rs);
}
void pushdown(int o)
{
	if(!rev[o]) return;
	if(ls) reverse(ls);
	if(rs) reverse(rs);
	rev[o]=0;
}
void rotate(int o,int d)
{
	int x=fa[o],y=fa[x],z=(ch[y][1]==x);
	if(!is_root(x)) ch[y][z]=o;
	ch[x][d^1]=ch[o][d],fa[ch[o][d]]=x;
	ch[o][d]=x,fa[x]=o,fa[o]=y;
	pushup(x),pushup(o),pushup(y);
}
int st[MAXN],top=0;
void splay(int o)
{
	st[++top]=o;
	for(int i=o;!is_root(i);i=fa[i])
		st[++top]=fa[i];
	while(top) pushdown(st[top--]);
	while(!is_root(o))
	{
		int x=fa[o],y=fa[x],d1=ch[x][0]==o,d2=ch[y][0]==x;
		if(is_root(x)) rotate(o,d1);
		else
		{
			if(d1==d2) rotate(x,d1),rotate(o,d1);
			else rotate(o,d1),rotate(o,d2);
		}
	}
}
void access(int o)
{
	int t=0;
	while(o)
	{
		splay(o),rs=t;
		pushup(o),t=o;
		o=fa[o];
	}
}
void make_root(int o)
{
	access(o),splay(o);
	reverse(o);
}
void cut(int u,int v)
{
	make_root(u);
	access(v),splay(v);
	ch[v][0]=fa[u]=0;
	pushup(v);
}
void join(int u,int v)
{
	make_root(u);
	fa[u]=v;
}
int find(int o)
{
	while(fa[o]) o=fa[o];
	return o;
}
int query(int u,int v)
{
	make_root(u),access(v),splay(v);
	return mx[v];
}
struct edge
{
	int u,v,t,tag;
	bool del;
	bool operator <(edge t)const
	{
		if(u==t.u)
			return v<t.v;
		return u<t.u;
	}
}e[M];
struct op{int k,a,b,id;}p[MAXN];
bool cmp(edge a,edge b){return a.t<b.t;}
void mst()
{
	int cnt=0;
	sort(e+1,e+1+m,cmp);
	for(int i=1;i<=n;i++)
		w[i]=-INF,mx[i]=i;
	for(int i=1;i<=m;i++)
		w[e[i].tag]=e[i].t,mx[e[i].tag]=e[i].tag;
	for(int i=1;i<=m;i++)
	{
		if(e[i].del) continue;
		if(find(e[i].u)!=find(e[i].v))
		{
			cnt++;
			join(e[i].u,e[i].tag);
			join(e[i].v,e[i].tag);
			if(cnt==n-1) break;
		}
	}
}
int main()
{
	n=read(),m=read(),q=read();
	for(int i=1;i<=m;i++)
	{
		e[i].u=read();
		e[i].v=read();
		e[i].t=read();
	}
	sort(e+1,e+1+m);
	for(int i=1;i<=m;i++)
		e[i].tag=n+i;
	for(int i=1;i<=q;i++)
	{
		p[i].k=read();
		p[i].a=read();
		p[i].b=read();
		if(p[i].k==2)
		{
			edge tmp; tmp.u=p[i].a,tmp.v=p[i].b;
			int idx=lower_bound(e+1,e+1+m,tmp)-e;
			e[idx].del=1,p[i].id=idx;
		}
	}
	mst();
	sort(e+1,e+1+m);
	for(int i=q;i;i--)
	{
		int u=p[i].a,v=p[i].b;
		if(p[i].k==1) ans.push_back(w[query(u,v)]);
		else
		{
			if(find(u)!=find(v))
			{
				join(u,e[p[i].id].tag);
				join(v,e[p[i].id].tag);
			}
			else 
			{
				int t=query(u,v),id=p[i].id;
				if(e[id].t>=w[t]) continue;
				cut(e[t-n].u,t);
				cut(e[t-n].v,t);
				join(id+n,u);
				join(id+n,v);
			}
		}
	}
	for(int i=ans.size()-1;i>=0;i--)
		printf("%d\n",ans[i]);
	return 0;
}

##BZOJ 3669 [Noi2014]魔法森林
按a排序后依次加边 维护最小生成树即可

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define M 100000*2
#define INF 1000000000
#define MAXN 100000*2
#define N 100000*2
#define ls ch[o][0]
#define rs ch[o][1]
using namespace std;
int read()
{
	int t=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
	return t*f;
}
int n,m,ans=INF;
int ch[MAXN][2],fa[MAXN],mx[MAXN],w[MAXN];
bool rev[MAXN];
struct edge
{
	int u,v,a,b;
	bool operator <(edge t)const{return a<t.a;}
}e[M];
bool is_root(int o)
{
	return (ch[fa[o]][0]!=o)&&(ch[fa[o]][1]!=o);
}
void reverse(int o)
{
	rev[o]^=1;
	swap(ls,rs);
}
void pushdown(int o)
{
	if(!rev[o]) return;
	if(ls) reverse(ls);
	if(rs) reverse(rs);
	rev[o]=0;
}
void pushup(int o)
{
	mx[o]=o;
	if(ls&&w[mx[ls]]>w[mx[o]]) mx[o]=mx[ls];
	if(rs&&w[mx[rs]]>w[mx[o]]) mx[o]=mx[rs];
}
void rotate(int o,int d)
{
	int x=fa[o],y=fa[x],z=ch[y][1]==x;
	if(!is_root(x)) ch[y][z]=o;
	ch[x][d^1]=ch[o][d],fa[ch[o][d]]=x;
	ch[o][d]=x,fa[x]=o,fa[o]=y;
	pushup(x),pushup(o),pushup(y);
}
int st[MAXN],top=0;
void splay(int o)
{
	st[++top]=o;
	for(int i=o;!is_root(i);i=fa[i])
		st[++top]=fa[i];
	while(top) pushdown(st[top--]);
	while(!is_root(o))
	{
		int x=fa[o],y=fa[x],d1=ch[x][0]==o,d2=ch[y][0]==x;
		if(is_root(x)) rotate(o,d1);
		else
		{
			if(d1==d2) rotate(x,d1),rotate(o,d2);
			else rotate(o,d1),rotate(o,d2);
		}
	}
}
void access(int o)
{
	int t=0;
	while(o)
	{
		splay(o),rs=t,pushup(o);
		t=o,o=fa[o];
	}
}
void make_root(int o){access(o),splay(o),reverse(o);}
void join(int u,int v){make_root(u),fa[u]=v;}
void cut(int u,int v)
{
	make_root(u),access(v),splay(v);
	ch[v][0]=fa[u]=0,pushup(v);
}
int find(int o)
{
	while(fa[o]) o=fa[o];
	return o;
}
int query(int u,int v)
{
	make_root(u),access(v),splay(v);
	return mx[v];
}
int main()
{
	n=read(),m=read();
	for(int i=1;i<=m;i++)
	{
		e[i].u=read();
		e[i].v=read();
		e[i].a=read();
		e[i].b=read();
	}
	sort(e+1,e+1+m);
	for(int i=1;i<=n;i++) mx[i]=i,w[i]=0;
	for(int i=1;i<=m;i++) mx[i+n]=i+m,w[i+n]=e[i].b;
	for(int i=1;i<=m;i++)
	{
		if(find(e[i].u)!=find(e[i].v))
		{
			join(e[i].u,i+n);
			join(e[i].v,i+n);
		}
		else
		{
			int t=query(e[i].u,e[i].v);
			if(e[i].b>=w[t]) continue;
			cut(e[t-n].u,t);
			cut(e[t-n].v,t);
			join(e[i].u,i+n);
			join(e[i].v,i+n);
		}
		if(find(1)==find(n)) ans=min(ans,e[i].a+w[query(1,n)]);
	}
	printf("%d\n",ans==INF?-1:ans);
	return 0;
}

##BZOJ 3514 Codechef MARCH14 GERALD07加强版

hzwer Orz
NTR大法好

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define M 200005*2
#define INF 1000000000
#define MAXN (200005*50)
#define N 200005
using namespace std;
int read()
{
	int t=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
	return t*f;
}

#define ls ch[o][0]
#define rs ch[o][1]
int fa[M],ch[M][2],mn[M],w[M];
bool rev[M];
bool is_root(int o){return (ch[fa[o]][0]!=o)&&(ch[fa[o]][1]!=o);}
void reverse(int o){rev[o]^=1,swap(ls,rs);}
void pushdown(int o)
{
	if(!rev[o]) return;
	if(ls) reverse(ls);
	if(rs) reverse(rs);
	rev[o]=0;
}
void pushup(int o)
{
	mn[o]=o;
	if(ls&&w[mn[ls]]<w[mn[o]]) mn[o]=mn[ls];
	if(rs&&w[mn[rs]]<w[mn[o]]) mn[o]=mn[rs];
}
void rotate(int o,int d)
{
	int x=fa[o],y=fa[x],z=ch[y][1]==x;
	if(!is_root(x)) ch[y][z]=o;
	ch[x][d^1]=ch[o][d],fa[ch[o][d]]=x;
	ch[o][d]=x,fa[x]=o,fa[o]=y;
	pushup(x),pushup(o),pushup(y);
}
int st[M],top=0;
void splay(int o)
{
	st[++top]=o;
	for(int i=o;!is_root(i);i=fa[i])
		st[++top]=fa[i];
	while(top) pushdown(st[top--]);
	while(!is_root(o))
	{
		int x=fa[o],y=fa[x],d1=ch[x][0]==o,d2=ch[y][0]==x;
		if(is_root(x)) rotate(o,d1);
		else
		{
			if(d1==d2) rotate(x,d1),rotate(o,d1);
			else rotate(o,d1),rotate(o,d2);
		}
	}
}
void access(int o)
{
	int t=0;
	while(o)
	{
		splay(o),rs=t;
		pushup(o);
		t=o,o=fa[o];
	}
}
void make_root(int o){access(o),splay(o),reverse(o);}
void join(int u,int v){make_root(u),fa[u]=v;}
void cut(int u,int v)
{
	make_root(u),access(v),splay(v);
	fa[u]=ch[v][0]=0,pushup(v);
}
int find(int o)
{
	while(fa[o])o=fa[o];
	return o;
}
int query(int u,int v)
{
	make_root(u),access(v),splay(v);
	return mn[v];
}

#define mid ((l+r)>>1)
#undef ls
#undef rs
int cnt=0;
int root[MAXN],ls[MAXN],rs[MAXN],s[MAXN];
void update(int pre,int &rt,int l,int r,int v)
{
	rt=++cnt,s[rt]=s[pre]+1;
	ls[rt]=ls[pre],rs[rt]=rs[pre];
	if(l==r) return;
	if(v<=mid) update(ls[pre],ls[rt],l,mid,v);
	else update(rs[pre],rs[rt],mid+1,r,v);
}
int ask(int rt,int l,int r,int nl,int nr)
{
	if(l==nl&&r==nr) return s[rt];
	if(nr<=mid) return ask(ls[rt],l,mid,nl,nr);
	else if(nl>mid) return ask(rs[rt],mid+1,r,nl,nr);
	else return ask(ls[rt],l,mid,nl,mid)+ask(rs[rt],mid+1,r,mid+1,nr);
}

int n,m,k,type,ntr[N];
struct edge{int u,v;}e[N];
int main()
{
	n=read(),m=read(),k=read(),type=read();
	w[0]=INF;
	for(int i=1;i<=m;i++)
	{
		e[i].u=read();
		e[i].v=read();
	}
	for(int i=1;i<=n;i++) mn[i]=i,w[i]=INF;
	for(int i=1;i<=m;i++) w[n+i]=i,mn[n+i]=n+i;
	for(int i=1;i<=m;i++)
	{
		if(e[i].u==e[i].v){ntr[i]=i;continue;}
		if(find(e[i].u)==find(e[i].v))
		{
			int t=query(e[i].u,e[i].v);
			ntr[i]=t-n;
			cut(t,e[t-n].u);
			cut(t,e[t-n].v);
		}
		join(e[i].u,i+n);
		join(e[i].v,i+n);
	}
	for(int i=1;i<=m;i++)
		update(root[i-1],root[i],0,m,ntr[i]);
	for(int i=1,ans=0;i<=k;i++)
	{
		int l=read(),r=read();
		if(type) l^=ans,r^=ans;
		int t=ask(root[r],0,m,0,l-1)-ask(root[l-1],0,m,0,l-1);
		printf("%d\n",ans=n-t);
	}
	return 0;
}

内容概要:该论文探讨了一种基于粒子群优化(PSO)的STAR-RIS辅助NOMA无线通信网络优化方法。STAR-RIS作为一种新型可重构智能表面,能同时反射和传输信号,与传统仅能反射的RIS不同。结合NOMA技术,STAR-RIS可以提升覆盖范围、用户容量和频谱效率。针对STAR-RIS元素众多导致获取完整信道状态信息(CSI)开销大的问题,作者提出一种在不依赖完整CSI的情况下,联合优化功率分配、基站波束成形以及STAR-RIS的传输和反射波束成形向量的方法,以最大化总可实现速率并确保每个用户的最低速率要求。仿真结果显示,该方案优于STAR-RIS辅助的OMA系统。 适合人群:具备一定无线通信理论基础、对智能反射面技术和非正交多址接入技术感兴趣的科研人员和工程师。 使用场景及目标:①适用于希望深入了解STAR-RIS与NOMA结合的研究者;②为解决无线通信中频谱资源紧张、提高系统性能提供新的思路和技术手段;③帮助理解PSO算法在无线通信优化问题中的应用。 其他说明:文中提供了详细的Python代码实现,涵盖系统参数设置、信道建模、速率计算、目标函数定义、约束条件设定、主优化函数设计及结果可视化等环节,便于读者理解和复现实验结果。此外,文章还对比了PSO与其他优化算法(如DDPG)的区别,强调了PSO在不需要显式CSI估计方面的优势。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值