在ISA的指点下,彻底理解了lct(以前可能学了假的lct)
这个题不难想,就是倒着加边然后维护链上信息。。
但这题常数巨卡,卡map卡开局不上kruskal卡多余splay卡少用splay。
一般这种题wc是要开o2的吧,,所以在开o2的网站上轻松跑过了,bzoj辣鸡
lct易错点:
1、isrt【】不是()
2、splay提前down,不提前down莫名错(理论上应该一样,但很玄学就是我写的不行)
3、up在set和access 稍微想一下就知道了
4、rev打标记不做,和线段树不一样(理论上应该一样,但很玄学就是我写的不行)
5、isrt分清fu和o
6、拆边做点注意数组i和i+n对应关系 (调了半天)
码(bzoj被卡,其他网站应该能过):
#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
#define N 1100005
map<int,map<int,int> >tu;
int v[N],maxx[N],from[N],n,m,q,i,j,ch[N][2],rev[N],fu[N],lx[N],a[N],b[N],ans[N],x[N],y[N];
bool bb[N] ;
int read()
{
char ch = getchar();
for ( ; ch > '9' || ch < '0'; ch = getchar());
int tmp = 0;
for ( ; '0' <= ch && ch <= '9'; ch = getchar())
tmp = tmp * 10 + int(ch) - 48;
return tmp;
}
int getwh(int o)
{
return ch[fu[o]][0]==o?0:1;
}
void up(int o)
{
maxx[o]=v[o];
from[o]=o;
if(ch[o][0]>0&&maxx[ch[o][0]]>maxx[o])
{
maxx[o]=maxx[ch[o][0]];
from[o]=from[ch[o][0]];
}
if(ch[o][1]>0&&maxx[ch[o][1]]>maxx[o])
{
maxx[o]=maxx[ch[o][1]];
from[o]=from[ch[o][1]];
}
}
void down(int o)
{
if(rev[o])
{
rev[o]^=1;
rev[ch[o][0]]^=1;
rev[ch[o][1]]^=1;
swap(ch[o][0],ch[o][1]);
}
}
bool isrt(int o)
{
if(fu[o]==0)return 1;
if(ch[fu[o]][0]==o||ch[fu[o]][1]==o)return 0;
return 1;
}
void set(int o,int wh,int child)
{
ch[o][wh]=child;
fu[child]=o;
up(o);
}
void rotate(int o)
{
int fa=fu[o];
int ye=fu[fa];
bool ysg=0;
if(isrt(fa))ysg=1;
int wh=getwh(o);
set(fa,wh,ch[o][wh^1]);
set(o,wh^1,fa);
fu[o]=ye;
if(ysg==0)ch[ye][ch[ye][0]==fa?0:1]=o;
}
int sta[N];
void splay(int o)
{
int top=0,i=o;sta[++top]=o;
for(;isrt(i)==0;i=fu[i])
{
sta[++top]=fu[i];
}
for(i=top;i>=1;i--)down(sta[i]);
int last=0;
for(;isrt(o)==0;rotate(o))
if(isrt(fu[o])==0)
getwh(fu[o])==getwh(o)?rotate(fu[o]):rotate(o);
}
void access(int o)
{
int last=0;
for(;o!=0;last=o,o=fu[o])
{
splay(o);
ch[o][1]=last;
up(o);
}
}
void huan(int o)
{
access(o);
splay(o);
rev[o]^=1;
}
void link(int x,int y)
{
huan(x);
fu[x]=y;
access(x);
}
void cut(int x,int y)
{
huan(x);
access(y);
splay(y);
ch[y][0]=fu[x]=0;
}
int main()
{
//freopen("tube_strong.in","r",stdin);
//freopen("tube_strong.out","w",stdout);
n=read();m=read();q=read();
for(i=1;i<=m;i++)
{
a[i]=read(),b[i]=read(),v[i+n]=read();
tu[a[i]][b[i]]=tu[b[i]][a[i]]=i;
}
for(i=1;i<=q;i++)
{
lx[i]=read(),x[i]=read(),y[i]=read();
if(lx[i]==2){
bb[tu[x[i]][y[i]]]=1;
}
}
for(i=1;i<=m;i++)
{
if(bb[i]==0)
{
// if(a[i]==7&&b[i]==14)
//cout<<endl<<a[i]<<" "<<b[i];
access(a[i]);
splay(a[i]);
int lin=a[i];
while(ch[lin][0]!=0)lin=ch[lin][0];
access(b[i]);
splay(b[i]);
int lin2=b[i];
while(ch[lin2][0]!=0)lin2=ch[lin2][0];
if(lin==lin2)
{
huan(a[i]);
access(b[i]);
splay(b[i]);
int lin3=from[b[i]];
if(maxx[b[i]]>v[i+n])
{
//if(lin3<n)cout<<"wocaonima";
cut(lin3,a[lin3-n]);
cut(lin3,b[lin3-n]);
link(a[i],i+n);
link(b[i],i+n);
}
}else
{
link(a[i],i+n);
link(i+n,b[i]);
}
}
}
for(j=q;j>=1;j--)
{
if(lx[j]==2)
{
i=tu[x[j]][y[j]];
access(a[i]);
splay(a[i]);
int lin=a[i];
while(ch[lin][0]!=0)lin=ch[lin][0];
access(b[i]);
splay(b[i]);
int lin2=b[i];
while(ch[lin2][0]!=0)lin2=ch[lin2][0];
huan(a[i]);
access(b[i]);
splay(b[i]);
int lin3=from[b[i]];
if(maxx[b[i]]>v[i+n])
{
cut(lin3,a[lin3-n]);
cut(lin3,b[lin3-n]);
link(a[i],i+n);
link(b[i],i+n);
}
}else
{
huan(x[j]);
access(y[j]);
splay(y[j]);
ans[j]=maxx[y[j]];
}
}
for(i=1;i<=q;i++)
{
if(lx[i]==1)
{
printf("%d\n",ans[i]);
}
}
}