[jzoj5786]【NOIP2008模拟】观察 (dfs序+lca)

传送门

Description

infleaking十分愉快地走在路上,
因为经过1099^9年后,
他得到了一个新技能——观察大法。

刚出来的infleaking就想要挑战自我。

为什么infleaking会这么自信呢?

因为infleaking做到了可以通过观察数据就就可以得出答案。

但是出题人十分不服,想要将infleaking的气焰打压下去,
于是想到了一道题。

结果被infleaking运用他那强大的观察能力看完数据后给出了答案。

怎么能够让infleaking继续下去呢,出题人于是就将数据重出并且加密了。
没有能直接观察数据的infleaking十分不服气,想要解决这道题,
但是苦于不能直接使用他的新技能,所以想要请聪明的你帮infleaking解决这个问题。

出题人给出一颗以1为根的树,一开始每个节点都是一颗棋子,一面白一面黑,白色的面朝上
接下来就q次操作,操作分两种
0操作 将一个颗棋子翻转
1操作 询问一颗棋子与所有面朝上为黑色的棋子lca最深的那个的编号

Input

第1行,两个正整数n,q
第2行,一共n-1个正整数,第i个正整数表示i+1号结点的父亲
第3~q+3每行两个整数x ,第|x|个为被操作的棋子,x>0操作为0否则为1

Output

对于每个op为1的操作输出对应的编号,若场上没有黑棋子输出0

Sample Input

10 10
6 2 7 9 1 10 5 4 3
-2
1
3
3
-5
8
1
4
-1
-5

Sample Output

0
1
1
5

Data Constraint

Solution

查询时找dfn序比它小和dfn序比它大的第一个黑点的lca即可
直接dfs会溢栈,不会手写栈,bfs水过qwq

Code

//By Menteur_Hxy
#pragma GCC diagnostic error "-std=c++11"
#pragma GCC optimize("-fdelete-null-pointer-checks,inline-functions-called-once,-funsafe-loop-optimizations,-fexpensive-optimizations,-foptimize-sibling-calls,-ftree-switch-conversion,-finline-small-functions,inline-small-functions,-frerun-cse-after-loop,-fhoist-adjacent-loads,-findirect-inlining,-freorder-functions,no-stack-protector,-fpartial-inlining,-fsched-interblock,-fcse-follow-jumps,-fcse-skip-blocks,-falign-functions,-fstrict-overflow,-fstrict-aliasing,-fschedule-insns2,-ftree-tail-merge,inline-functions,-fschedule-insns,-freorder-blocks,-fwhole-program,-funroll-loops,-fthread-jumps,-fcrossjumping,-fcaller-saves,-fdevirtualize,-falign-labels,-falign-loops,-falign-jumps,unroll-loops,-fsched-spec,-ffast-math,Ofast,inline,-fgcse,-fgcse-lm,-fipa-sra,-ftree-pre,-ftree-vrp,-fpeephole2",3)
#pragma GCC target("avx","sse2")
//以上自动忽略qwq
#include<set>
#include<cstdio>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define int long long
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
#define R(i,a,b) for(register int i=(b);i>=(a);i--)
#define E(i,u) for(register int i=head[u];i;i=nxt[i])
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2?EOF:*p1++)
using namespace std;
typedef long long LL;

char buf[1<<21],*p1,*p2;
inline int read() {
	int x=0,f=1; char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
	while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
	return x*f;
}

const int N=800010;
int n,q,tot,cnt;
int dfn[N],id[N],f[N][24],dep[N],nxt[N],to[N],head[N],siz[N],que[N];
set <int> S;
set <int>::iterator it;

int lca(int x,int y) {
	if(dep[x]<dep[y]) swap(x,y);
	int need=dep[x]-dep[y];
	for(int i=0;need;need>>=1,i++) if(need&1) x=f[x][i];
	if(x!=y) {
		R(i,0,21) if(f[x][i]!=f[y][i]) 
			x=f[x][i],y=f[y][i];
		return f[x][0];
	}
	return x;
}

void dfs(int u) {
	siz[u]=1;
	dfn[u]=++tot; id[dfn[u]]=u;
	E(i,u) {
		int v=to[i];
		dep[v]=dep[u]+1;
		f[v][0]=u;
		dfs(v);
		siz[u]+=siz[v];
	}
}

void bfs1() {
	int h=0,t=1;
	que[++h]=1;
	while(h<=t) {
		int u=que[h++];
		siz[u]=1;
		E(i,u) {
			int v=to[i];
			dep[v]=dep[u]+1,f[v][0]=u;
			que[++t]=v;
		}
	}
	R(i,1,n) siz[f[que[i]][0]]+=siz[que[i]];
}

void bfs2() {
	int h=0,t=1;
	que[++h]=1;dfn[1]=1; id[dfn[1]]=1;
	while(h<=t) {
		int u=que[h++],last=u;
		E(i,u) {
			int v=to[i];
			dfn[v]=dfn[last]+(last!=u?siz[last]:1);
			id[dfn[v]]=v;
			que[++t]=v;
			last=v;
		}
	}
}

#define add(a,b) nxt[++cnt]=head[a],to[cnt]=b,head[a]=cnt
signed main() {
	freopen("watch.in","r",stdin);
	freopen("watch.out","w",stdout);
	n=read(),q=read();
	F(i,1,n-1) {int u=read();add(u,i+1);}
//	dfs(1); 通往溢栈的钥匙233
	bfs1(),bfs2();
//	F(i,1,n) printf("%d ",dep[i]);putchar('\n');
	for(register int j=1;(1<<j)<=n;j++) 
		F(i,1,n) if(f[i][j-1]) 
			f[i][j]=f[f[i][j-1]][j-1];
	dep[0]=-1;
	F(i,1,q) {
		int x=read(),fla=0;
		if(x<0) fla=1,x=-x;
		if(!fla) {
			if(!S.insert(dfn[x]).second) S.erase(dfn[x]);
			continue;
		}
		if(S.empty()) {
			putchar('0');
			putchar('\n');
			continue;
		}
		int t1=0,t2=0;
		it=S.lower_bound(dfn[x]);
		if(it!=S.end()) t1=lca(x,id[*it]);
		if(it!=S.begin()) it--,t2=lca(x,id[*it]);
//		__builtin_printf("%d %d\n",t1,t2);
		if(dep[t1]<dep[t2]) printf("%d\n",t2);
		else printf("%d\n",t1);
	}
	return 0;
}
posted @ 2018-08-10 18:50  Menteur_hxy  阅读(682)  评论(0编辑  收藏  举报