400字范文,内容丰富有趣,生活中的好帮手!
400字范文 > nssl1164-观察【平衡树 LCA】

nssl1164-观察【平衡树 LCA】

时间:2022-04-20 15:28:20

相关推荐

nssl1164-观察【平衡树 LCA】

正题

题目大意

一棵树,开始全是白点,两个操作

将一个节点翻转询问一颗棋子与所有面朝上为黑色的棋子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 800010using 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');}//求最近的}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。