好久的坑了,今天终于填上了。
一直想总结一下LCT,结果发现难题都不会做。
离线处理,因为删边比较难做,所以我们倒着做变成加边操作。
问题转化成加边维护最小生成树,用lct维护一下最大的边是哪一条,一旦新加入的边形成环了,那么看一看环上最大的边和新加入的边哪个大,如果新加入的边小,那么删除原来的边,加入这一条边。
竟然1A,简直不可思议,不过时间慢成狗。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#define maxn 1500010
using namespace std;
struct yts
{
int x,y,id,z;
int tag;
}e[1000010];
struct yts1
{
int op,x,y,ans,id;
}q[100010];
int fa[maxn],ch[maxn][2],val[maxn],mx[maxn];
bool rev[maxn];
int f[100010];
int n,m,T,tot,num;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
bool cmp1(yts x,yts y)
{
return x.x<y.x || (x.x==y.x && x.y<y.y);
}
int find(int x,int y)
{
int l=1,r=m,ans;
while (l<=r)
{
int mid=(l+r)/2;
if (e[mid].x==x && e[mid].y==y) return mid;
if (e[mid].x<x || (e[mid].x==x && e[mid].y<y)) ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
bool cmp2(yts x,yts y)
{
return x.z<y.z;
}
bool cmp3(yts x,yts y)
{
return x.id<y.id;
}
int dir(int x)
{
return x==ch[fa[x]][1];
}
int isroot(int x)
{
return !(x==ch[fa[x]][0] || x==ch[fa[x]][1]);
}
void push_up(int x)
{
mx[x]=x;
if (val[mx[ch[x][0]]]>val[mx[x]]) mx[x]=mx[ch[x][0]];
if (val[mx[ch[x][1]]]>val[mx[x]]) mx[x]=mx[ch[x][1]];
}
void reverse(int x)
{
rev[x]^=1;
swap(ch[x][0],ch[x][1]);
}
void push_down(int x)
{
if (rev[x])
{
if (ch[x][0]) reverse(ch[x][0]);
if (ch[x][1]) reverse(ch[x][1]);
rev[x]^=1;
}
}
void rotate(int x)
{
int y=fa[x],z=fa[y],b=dir(x),a=ch[x][!b],c=dir(y);
if (!isroot(y)) ch[z][c]=x;
fa[x]=z;fa[y]=x;ch[x][!b]=y;ch[y][b]=a;
if (a) fa[a]=y;
push_up(y);push_up(x);
}
void down(int x)
{
if (!isroot(x)) down(fa[x]);
push_down(x);
}
void splay(int x)
{
down(x);
while (!isroot(x))
{
int y=fa[x];
if (isroot(y)) rotate(x);
else
{
int b=dir(x),c=dir(y);
if (b^c)
{
rotate(x);rotate(x);
}
else
{
rotate(y);rotate(x);
}
}
}
}
void access(int x)
{
for (int y=0;x;y=x,x=fa[x])
{
splay(x);
ch[x][1]=y;
push_up(x);
}
}
void make_root(int x)
{
access(x);
splay(x);
reverse(x);
}
void cut(int x,int y)
{
make_root(x);
access(x);
splay(y);
fa[y]=0;
}
void link(int x,int y)
{
make_root(x);
fa[x]=y;
}
int query(int x,int y)
{
make_root(x);
access(y);
splay(y);
return mx[y];
}
int find(int x)
{
if (f[x]==x) return x;
else return f[x]=find(f[x]);
}
int main()
{
n=read();m=read();T=read();
for (int i=1;i<=m;i++) {e[i].x=read();e[i].y=read();e[i].z=read();if (e[i].x>e[i].y) swap(e[i].x,e[i].y);}
sort(e+1,e+m+1,cmp2);
for (int i=1;i<=m;i++) {e[i].id=i;val[i+n]=e[i].z;mx[i+n]=i+n;}
sort(e+1,e+m+1,cmp1);
for (int i=1;i<=T;i++)
{
q[i].op=read();q[i].x=read();q[i].y=read();
if (q[i].x>q[i].y) swap(q[i].x,q[i].y);
if (q[i].op==2)
{
int x=find(q[i].x,q[i].y);
q[i].id=e[x].id;
e[x].tag=1;
}
}
sort(e+1,e+m+1,cmp3);
for (int i=1;i<=n;i++) f[i]=i;
for (int i=1;i<=m;i++)
if (!e[i].tag)
{
int f1=find(e[i].x),f2=find(e[i].y);
if (f1!=f2)
{
num++;
link(e[i].x,i+n);link(e[i].y,i+n);
f[f1]=f2;
if (num==n-1) break;
}
}
for (int i=T;i>=1;i--)
{
if (q[i].op==1) q[i].ans=val[query(q[i].x,q[i].y)];
else
{
int x=query(q[i].x,q[i].y);
if (e[q[i].id].z<val[x]) cut(e[x-n].x,x),cut(e[x-n].y,x),link(q[i].x,q[i].id+n),link(q[i].y,q[i].id+n);
}
}
for (int i=1;i<=T;i++)
if (q[i].op==1) printf("%d\n",q[i].ans);
return 0;
}