突然回想起之前板刷了LCT题单的,那么不是意味着LCT都不用写了么233
这题还算比较简单且套路,最大值最小想到维护原图的最小生成树,这里用LCT维护
那么删边太麻烦了,我们离线之后倒着做,把删除改成插入
那么对于新加入的一条边,显然我们把它的边权和本来两点间的路径上的边权最大边进行对比一下看看是否要替换即可
PS:花了30min才复习完了LCT板子,发现我的水平急剧下降,记得当时可以10min写出LCT的,现在……
#include
#include
#include
#define RI register int
#define CI const int&
#define Tp template
using namespace std;
const int N=100005,M=1000005;
struct edge
{
int x,y,v,id; bool iscut;
}e[M]; int n,m,q_tot,ans[N];
struct ques
{
int opt,x,y,id;
}q[N]; int val[N+M];
inline bool cmpx(const edge& A,const edge& B)
{
return A.x>1; if (e[mid].x==x&&e[mid].y==y) return mid;
if (e[mid].xval[mx(now)]) mx(now)=mx(lc(now));
if (val[mx(rc(now))]>val[mx(now)]) mx(now)=mx(rc(now));
}
inline void pushdown(CI now)
{
if (node[now].rev) rever(lc(now)),rever(rc(now)),node[now].rev=0;
}
inline int identify(CI now)
{
return rc(fa(now))==now;
}
inline void connect(CI x,CI y,CI d)
{
node[fa(x)=y].ch[d]=x;
}
inline bool isroot(CI now)
{
return lc(fa(now))!=now&&rc(fa(now))!=now;
}
inline void rotate(CI now)
{
int x=fa(now),y=fa(x),d=identify(now); if (!isroot(x)) node[y].ch[identify(x)]=now;
fa(now)=y; connect(node[now].ch[d^1],x,d); connect(x,now,d^1); pushup(x); pushup(now);
}
inline void splay(CI now)
{
int t=now; while (stack[++top]=t,!isroot(t)) t=fa(t);
while (top) pushdown(stack[top--]); for (;!isroot(now);rotate(now))
t=fa(now),!isroot(t)&&(rotate(identify(now)!=identify(t)?now:t),0);
}
inline void access(int x)
{
for (int y=0;x;x=fa(y=x)) splay(x),rc(x)=y,pushup(x);
}
inline int findroot(int now)
{
access(now); splay(now); for (;lc(now);now=lc(now)) pushdown(now); return splay(now),now;
}
inline void makeroot(CI now)
{
access(now); splay(now); rever(now);
}
inline void split(CI x,CI y)
{
makeroot(x); access(y); splay(y);
}
public:
inline void insert(CI x,CI y)
{
val[x]=y; node[x].mx=x;
}
inline void link(CI x,CI y)
{
makeroot(x); splay(x); if (findroot(y)!=x) fa(x)=y;
}
inline void cut(CI x,CI y)
{
makeroot(x); splay(y); if (findroot(y)==x&&fa(y)==x&&!lc(y)) rc(x)=fa(y)=0,pushup(x);
}
inline int query(CI x,CI y)
{
return split(x,y),node[y].mx;
}
#undef lc
#undef rc
#undef fa
#undef mx
}LCT;
class UnionFindSet
{
private:
int father[N],size[N];
inline int getfather(CI x)
{
return father[x]!=x?father[x]=getfather(father[x]):x;
}
public:
inline void init(void)
{
for (RI i=1;i<=n;++i) father[i]=i,size[i]=1;
}
inline bool identify(CI x,CI y)
{
return getfather(x)==getfather(y);
}
inline void Union(CI x,CI y,CI id)
{
int fx=getfather(x),fy=getfather(y);
LCT.link(n+id,x); LCT.link(n+id,y);
if (size[fx]e[i].y) swap(e[i].x,e[i].y);
}
for (sort(e+1,e+m+1,cmpv),i=1;i<=m;++i) e[i].id=i,LCT.insert(n+i,e[i].v);
for (sort(e+1,e+m+1,cmpx),i=1;i<=q_tot;++i)
{
F.read(q[i].opt); F.read(q[i].x); F.read(q[i].y);
if (q[i].opt==1) continue; if (q[i].x>q[i].y) swap(q[i].x,q[i].y);
int pos=find(q[i].x,q[i].y); e[pos].iscut=1; q[i].id=e[pos].id;
}
for (sort(e+1,e+m+1,cmpid),S.init(),i=1;i<=m;++i)
if (!e[i].iscut&&!S.identify(e[i].x,e[i].y)) S.Union(e[i].x,e[i].y,i);
for (i=q_tot;i;--i)
{
if (q[i].opt==1) { ans[i]=val[LCT.query(q[i].x,q[i].y)]; continue; }
int pos=LCT.query(q[i].x,q[i].y); if (e[q[i].id].v