jzoj 4811. 【NOIP2016提高A组五校联考1】排队

Question

在这里插入图片描述

Solution

考后听别人打得都是什么树剖,线段树,堆。。。
感觉自己打的个链表有点虚啊。。。
我们先弄一个后序遍历,将其中的每一位指向它的下一位,设为to[i]to[i]
我们设laslas表示后序遍历中最前的未被标记的点的位置。

操作一:

我们只需跳x次并将每个位置都标记一下即可。并将laslas更新。
输出跳到最后的位置。

操作二:

我们用倍增跳到它的最远的标记过的祖先。
将这个标记删除,设这个位置为kk
如果k<lask<las,就将to[k]=lasto[k]=las,并将laslas改成kk即可。
如果k>lask>las,我们就用另一个变量(设为oo)跳到一个位置,使得to[o]>kto[o]>k
就将to[k]=to[o],to[o]=kto[k]=to[o],to[o]=k即可。
输出祖先的深度减去输入的x的深度即可。

Code

#include<cstdio>
#include<algorithm>
#define N 100010
using namespace std;
struct node{int u,v;}e[N<<1];
int n,T,e1[N],e2[N],now,dep[N],hav[N],to[N];
int fa[N][17],s=0,dfn[N],fr[N],tot=0,las=1;

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

int cmp(node x,node y) {return x.u==y.u ? x.v<y.v : x.u<y.u;}

void dfs(int x)
{
	if (!e2[x]) {dfn[++tot]=x; fr[x]=tot; return;}
	for (int p=e1[x],v;p<=e2[x];p++)
	{
		v=e[p].v;
		if (v==fa[x][0]) continue;
		dep[v]=dep[x]+1,fa[v][0]=x,dfs(v);
	}
	dfn[++tot]=x;
	fr[x]=tot;
}

int main()
{
	n=read(),T=read();to[0]=1;to[n]=n+1;
	for (int i=1;i<n;i++)
	{
		e[(i<<1)-1].u=read(),e[(i<<1)-1].v=read();
		e[i<<1].v=e[(i<<1)-1].u,e[i<<1].u=e[(i<<1)-1].v;
		to[i]=i+1;
	}
	sort(e+1,e+n+n-1,cmp);
	e1[e[1].u]=1;
	for (int i=2;i<=n+n-2;i++)
		if (e[i].u!=e[i-1].u)
			e2[e[i-1].u]=i-1,e1[e[i].u]=i;
	e2[e[n+n-2].u]=n+n-2;
	dfs(1);
	for (int j=1;j<=16;j++)
		for (int i=1;i<=n;i++)
			fa[i][j]=fa[fa[i][j-1]][j-1];
	for (int i=1,opt,x;i<=T;i++)
	{
		opt=read(),x=read();
		if (opt==1)
		{
			now=las;hav[now]=1;x--;
			while (x--) now=to[now],hav[now]=1;
			las=to[now];printf("%d\n",dfn[now]);
		}
		else
		{
			s=dep[x];
			for (int j=16;j>=0;j--)
				if (hav[fr[fa[x][j]]]) x=fa[x][j];
			if (fr[x]<las) to[fr[x]]=las,las=fr[x];
			else
			{
				now=las;
				while (to[now]<fr[x]) now=to[now];
				to[fr[x]]=to[now],to[now]=fr[x];
			}
			hav[fr[x]]=0;
			printf("%d\n",s-dep[x]);
		}
	}
	return 0;
}
posted @ 2019-07-03 19:41  jz929  阅读(88)  评论(0编辑  收藏  举报