1. 程式人生 > >【UOJ274】【清華集訓2016】溫暖會指引我們前行 LCT

【UOJ274】【清華集訓2016】溫暖會指引我們前行 LCT

while atom 滿足 inline 情況下 排序 review 不同 輸出格式

【UOJ274】【清華集訓2016】溫暖會指引我們前行

任務描述

雖然小R住的宿舍樓早已來了暖氣,但是由於某些原因,宿舍樓中的某些窗戶仍然開著(例如廁所的窗戶),這就使得宿舍樓中有一些路上的溫度還是很低。

小R的宿舍樓中有n個地點和一些路,一條路連接了兩個地點,小R可以通過這條路從其中任意一個地點到達另外一個地點。但在剛開始,小R還不熟悉宿舍樓中的任何一條路,所以他會慢慢地發現這些路,他在發現一條路時還會知道這條路的溫度和長度。每條路的溫度都是互不相同的。

小R需要在宿舍樓中活動,每次他都需要從一個地點到達另一個地點。小R希望每次活動時經過一條最溫暖的路徑,最溫暖的路徑的定義為,將路徑上各條路的溫度從小到大排序後字典序最大。即溫度最低的路溫度盡量高,在滿足該條件的情況下,溫度第二低的路溫度盡量高,以此類推。小R不會經過重復的路。由於每條路的溫度互不相同,因此只存在一條最溫暖的路徑。

對於小R的每次活動,你需要求出小R需要走過的路徑總長度。如果小R通過當前發現的路不能完成這次活動,則輸出 1

註意本題中的字典序與傳統意義上的字典序定義有所不同,對於兩個序列a,b(ab),若a是b的前綴則a的字典序較大,同時可以推出空串的字典序最大。

輸入格式

第一行兩個正整數 n,m。表示小R的宿舍樓中有 n 個地點,共發生了 m 個事件。

接下來 m 行,每行描述一個事件,事件分為三類。

  1. find id u v t l 表示小R發現了一條連接u和v之間的路,編號為id。相同id的邊只會出現一次。

  2. move u v 表示小R要從u到達

    v,你需要計算出最溫暖的路徑的長度 ,若不能從u到達v,則輸出−1。

  3. change id l 表示從u到v這條邊的長度變為了l(保證在當前時間點這條邊存在)。

輸出格式

對於每個詢問,輸出一行整數,表示最溫暖的路徑長度。

題解:裸題,直接用LCT維護最大生成樹即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100010;
int n,m,tot;
struct LCT
{
	int ch[2],fa,rev,v,vn,l,sl;
}s[maxn<<2];
int f[maxn],pa[maxn<<2],pb[maxn<<2];
char str[10];
inline bool isr(int x) {return (s[s[x].fa].ch[0]!=x)&&(s[s[x].fa].ch[1]!=x);}
inline void pushdown(int x)
{
	if(s[x].rev)
	{
		swap(s[x].ch[0],s[x].ch[1]);
		if(s[x].ch[0])	s[s[x].ch[0]].rev^=1;
		if(s[x].ch[1])	s[s[x].ch[1]].rev^=1;
		s[x].rev=0;
	}
}
inline int MN(int a,int b) {return s[a].v<s[b].v?a:b;}
inline void pushup(int x)
{
	s[x].vn=MN(MN(s[s[x].ch[0]].vn,s[s[x].ch[1]].vn),x);
	s[x].sl=s[s[x].ch[0]].sl+s[s[x].ch[1]].sl+s[x].l;
}
inline void rotate(int x)
{
	int y=s[x].fa,z=s[y].fa,d=(x==s[y].ch[1]);
	if(!isr(y))	s[z].ch[y==s[z].ch[1]]=x;
	s[x].fa=z,s[y].fa=x,s[y].ch[d]=s[x].ch[d^1];
	if(s[x].ch[d^1])	s[s[x].ch[d^1]].fa=y;
	s[x].ch[d^1]=y;
	pushup(y),pushup(x);
}
void updata(int x)
{
	if(!isr(x))	updata(s[x].fa);
	pushdown(x);
}
inline void splay(int x)
{
	updata(x);
	while(!isr(x))
	{
		int y=s[x].fa,z=s[y].fa;
		if(!isr(y))
		{
			if((x==s[y].ch[0])^(y==s[z].ch[0]))	rotate(x);
			else	rotate(y);
		}
		rotate(x);
	}
}
inline void access(int x)
{
	for(int y=0;x;splay(x),s[x].ch[1]=y,pushup(x),y=x,x=s[x].fa);
}
inline void maker(int x)
{
	access(x),splay(x),s[x].rev^=1;
}
inline void link(int x,int y)
{
	maker(y),s[y].fa=x;
}
inline void cut(int x,int y)
{
	maker(x),access(y),splay(y),s[y].ch[0]=s[x].fa=0,pushup(x),pushup(y);
}
int find(int x)
{
	return (f[x]==x)?x:(f[x]=find(f[x]));
}
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)	f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+(gc^‘0‘),gc=getchar();
	return ret*f;
}
int main()
{
	//freopen("bz4736.in","r",stdin);
	s[0].v=1<<30;
	n=rd(),m=rd();
	int i,a,b,c,e;
	for(i=1;i<=n;i++)	f[i]=i,s[i].v=1<<30,s[i].vn=i;
	for(i=1;i<=m;i++)
	{
		scanf("%s",str);
		if(str[0]==‘f‘)
		{
			e=n+rd()+1,a=pa[e]=rd()+1,b=pb[e]=rd()+1,s[e].v=rd(),s[e].vn=e,s[e].l=s[e].sl=rd();
			if(find(a)==find(b))
			{
				maker(a),access(b),splay(b),c=s[s[b].ch[0]].vn;
				if(s[c].v<s[e].v)	cut(c,pa[c]),cut(c,pb[c]),link(a,e),link(b,e);
			}
			else	f[f[a]]=f[b],link(a,e),link(b,e);
		}
		if(str[0]==‘m‘)
		{
			a=rd()+1,b=rd()+1;
			if(find(a)!=find(b))	puts("-1");
			else	maker(a),access(b),splay(b),printf("%d\n",s[s[b].ch[0]].sl);
		}
		if(str[0]==‘c‘)	e=n+rd()+1,splay(e),s[e].l=rd(),pushup(e);
	}
	return 0;
}

【UOJ274】【清華集訓2016】溫暖會指引我們前行 LCT