COCI2014 stogovi

題目描述:

Mirko在玩堆棧遊戲。開始他有一個空的堆棧,編號爲0.在第i步(1<=i<=300000),他會選擇一個編號爲v的堆棧,做如下操作:
1.a v 表示將v號堆棧複製一份,新棧的編號爲i,並將元素i壓入新棧的棧頂。
2. b v 表示將v號堆棧複製一份,新棧的編號爲i,將新棧的棧頂元素彈出。
3.c v w 將v號堆棧複製一份,編號爲i,並比較第v號和第w號堆棧中有多少相同的數。

輸入:

第一行一個整數n,表示有n步。
接下來n步,每步表示一個操作,如上所述。

輸出:

對所有的b操作和c操作,輸出結果,每行一個。b操作需要輸出該棧移除的元素,c操作表示兩個堆棧的相同的數的個數。

樣例輸入:

5
a 0
a 1
b 2
c 2 3
b 4

樣例輸出:

2
1
2

分析:

這是一道比較神的題。用堆棧打掩護,其實是一道LCA的題。在考試的時候雖然隱約感覺這些操作與之前的堆棧有所聯繫,但沒有明確的想出來怎樣建圖(以前沒怎麼獨立做過LCA的題),亂碼了200行,一分沒有……下來自己又碼了一邊,居然一邊就A了,可能跟我抄了接近十遍的NOIP2013 day2 truck 有很大的關係吧。“a”操作我們將它翻譯爲在相關節點連一條父子邊,i爲輸入的x的兒子;“b”操作翻譯爲將i與輸入的x的父親合併在一起,並輸出x的棧頂元素;“c”操作翻譯爲將i與輸入的x1合併,尋找i與輸入的x2的最近公共祖先,並輸出它的深度。因爲題目中給出信息每一次壓入堆棧的元素並不相同,所以不用擔心在lca(i,x2)後面會有相同的數,就可以直接輸出deep[lca(i,x2)]。

code:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 300000
#define MAXD 20
using namespace std;
int fa[MAXN+5][MAXD+5],deep[MAXN+5];
int unit[MAXN+5],top[MAXN+5];
int n,d1,d2;
char o[2];
int find(int x){return unit[x]==x?x:unit[x]=find(unit[x]);}
void dfs(int u,int f)
{
	int i;
	fa[u][0]=f;
	deep[u]=deep[f]+1;
	for(i=1;i<=MAXD;i++)
	{
		if(deep[u]<(1<<i))
			break;
		fa[u][i]=fa[fa[u][i-1]][i-1];
	}
}
int lca(int u,int v)
{
	if(deep[u]<deep[v])
		swap(u,v);
	int i,t=deep[u]-deep[v];
	for(i=0;i<=MAXD;i++)
		if((1<<i)&t)
			u=fa[u][i];
	for(i=MAXD;i>=0;i--)
		if(fa[u][i]!=fa[v][i])
		{
			u=fa[u][i];
			v=fa[v][i];
		}
	if(u==v)
		return u;
	return fa[u][0];
}
int main()
{
	int i;
	scanf("%d",&n);
	memset(fa,-1,sizeof fa);
	for(i=1;i<=n;i++)
		unit[i]=i;
	for(i=1;i<=n;i++)
	{
		scanf("%s",o);
		if(o[0]=='a')
		{
			scanf("%d",&d1);
			d1=find(d1);
			dfs(i,d1);
			top[i]=i;
		}
		else if(o[0]=='b')
		{
			scanf("%d",&d1);
			d1=find(d1);
			int f=find(fa[d1][0]);
			top[i]=top[f];
			dfs(i,f);
			unit[i]=f;
			printf("%d\n",top[d1]);
		}
		else if(o[0]=='c')
		{
			scanf("%d%d",&d1,&d2);
			d1=find(d1),d2=find(d2);
			top[i]=top[d1];
			int f1=find(fa[d1][0]),f2=find(d2);
			dfs(i,f1);
			unit[i]=d1;
			int fi=find(i);
			printf("%d\n",deep[lca(fi,f2)]);
		}
	}
}


發佈了34 篇原創文章 · 獲贊 4 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章