2017.10.16 水管局长&&水管局长数据加强版 思考记录

在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
#include
#include
using namespace std;
#define N 1100005
map >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<v[i+n])
			{
				//if(lin3=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]);
		}
	}
}



你可能感兴趣的:(题目)