版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/82855481
正题
题目大意
一棵树,开始全是白点,两个操作
- 将一个节点翻转
- 询问一颗棋子与所有面朝上为黑色的棋子lca最深的那个的编号
解题思路
必备技能:平衡树(或set库的使用方法),大量卡常技巧,LCA
我们可以发现和一个点的lca最深的话,这个点一定是在dfs序上最近的点,这时候我们就要使用平衡树了。
每多一个黑点就将dfs序加入平衡树,删除就去掉。然后询问一个点的时候就在平衡树上查询离他dfs最近的一个黑点,然后求LCA。
这里就不敲平衡树了,反正set也行
不过直接用dfs会爆炸,所以要用奇特的方法计算dfs序。
code
注意:以下代码包含大量卡常操作,如果对您的眼睛造成了伤害那我表示道歉。
#pragma GCC optimize("O2")
#include<cstdio>
#include<algorithm>
#include<set>
#include<cmath>
#include<queue>
#include<cctype>
#define N 800010
using namespace std;
struct line{
int to,next,w;
}a[N];
int tot,n,m,x,y,ls[N],dep[N],t,cnt,T,que[N];
int dfn[N],put[N],f[N][24],dis[N][24],siz[N];
set<int> s;
queue<int> q;
__attribute__((optimize("O3"))) 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;
}
__attribute__((optimize("O3"))) inline void addl(int x,int y)
{
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;
}
__attribute__((optimize("O3"))) void dfs()//求dfs序
{
int h=0,t=1;
que[++h]=1;dfn[1]=1; put[dfn[1]]=1;
while(h<=t) {
int x=que[h++],last=x;
for(register int i=ls[x];i;i=a[i].next)
{
int y=a[i].to;
dfn[y]=dfn[last]+(last!=x?siz[last]:1);
put[dfn[y]]=y;
que[++t]=y;
last=y;
}
}
}
__attribute__((optimize("O3"))) void bfs(int s)//预处理LCA
{
int h=0,t=1;
que[++h]=1;
while(h<=t) {
int x=que[h++];
siz[x]=1;
for(register int i=ls[x];i;i=a[i].next) {
int y=a[i].to;
dep[y]=dep[x]+1,f[y][0]=x;
que[++t]=y;
}
}
for(register int i=n;i>=1;i--)
siz[f[que[i]][0]]+=siz[que[i]];
T=(int)(log(n)/log(2))+1;
for (int j=1;j<=T;j++)
{
for (int i=1;i<=n;i++)
{
f[i][j]=f[f[i][j-1]][j-1];
dis[i][j]=min(dis[i][j-1],dis[f[i][j-1]][j-1]);
}
}
cnt=0;
}
__attribute__((optimize("O3"))) int LCA(int x,int y)//求LCA
{
if (dep[x]>dep[y]) swap(x,y);
for (int i=T;i>=0;i--)
if (dep[f[y][i]]>=dep[x]) y=f[y][i];
if (x==y) return x;
for (int i=T;i>=0;i--)
if (f[y][i]!=f[x][i])
{
x=f[x][i];
y=f[y][i];
}
return f[x][0];
}
__attribute__((optimize("O3"))) void print(int x){
if (x>9) print(x/10); putchar(x%10+48); return;
}
__attribute__((optimize("O3"))) signed main()
{
n=read();m=read();
for(register int i=2;i<=n;i++)
{
addl(read(),i);
}
bfs(1);
dfs();
dep[0]=-1;
for(register int i=1;i<=m;i++)
{
x=read();
if(x>0)
{
if(!s.insert(dfn[x]).second) s.erase(dfn[x]);
//加点or去点
}
else
{
x=abs(x);
int t1=0,t2=0;
set<int>::iterator y=s.lower_bound(dfn[x]);
if(y!=s.end()) t1=LCA(x,put[*y]);
if(y!=s.begin()) y--,t2=LCA(x,put[*y]);
if(dep[t1]<dep[t2]) print(t2),putchar('\n');
else print(t1),putchar('\n');
}//求最近的
}
}