bzoj4764: 弹飞大爷 link-cut-tree

时间:2023-03-09 13:01:46
bzoj4764: 弹飞大爷 link-cut-tree

题目传送门

这道题啊 调了一个晚上 因为写的是一个有根树和n个基环的写法 所以写得很奇怪..... 最后发现单独处理树的时候不能随意改变S(就是原来的根)不然size会出错....

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int M=;
int read(){
int ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
int c[M][],fa[M],size[M],rev[M],lx[M],rx[M],sum[M];
int n,m;
bool isrt(int x){return c[fa[x]][]!=x&&c[fa[x]][]!=x;}
void up(int x){size[x]=size[c[x][]]+size[c[x][]]+;}
void down(int x){
int l=c[x][],r=c[x][];
if(rev[x]){
if(l) swap(c[l][],c[l][]),rev[l]^=;
if(r) swap(c[r][],c[r][]),rev[r]^=;
rev[x]=;
}
int u=lx[x],v=rx[x];
if(l) lx[l]=u,rx[l]=v;
if(r) lx[r]=u,rx[r]=v;
}
void rotate(int x){
int y=fa[x],z=fa[y],l=,r=;
if(c[y][]==x) l=,r=;
if(!isrt(y)) c[z][c[z][]==y]=x;
fa[y]=x; fa[x]=z; fa[c[x][r]]=y;
c[y][l]=c[x][r]; c[x][r]=y;
up(y); up(x);
}
int st[M],top=,S;
void splay(int x){
st[++top]=x; for(int i=x;!isrt(i);i=fa[i]) st[++top]=fa[i];
while(top) down(st[top--]);
while(!isrt(x)){
int y=fa[x],z=fa[y];
if(!isrt(y)){
if(c[z][]==y^c[y][]==x) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void acs(int x0){
for(int x=x0,y=;x;splay(x),c[x][]=y,up(x),y=x,x=fa[x]);
splay(x0);
}
void mrt(int x){acs(x); swap(c[x][],c[x][]); rev[x]^=;}
int find(int x){
acs(x); while(c[x][]) x=c[x][];
return x;
}
void push_link(int x,int y){mrt(x); fa[x]=y; acs(x);}
void link(int x,int y){
if(find(x)==find(y)) lx[y]=x,rx[y]=y;
else push_link(x,y);
}
int push_ans(int x){
acs(x); if(lx[x]&&rx[x]) return -;
return size[x]-;
}
void cut(int x,int y){mrt(x); acs(y); c[y][]=fa[x]=; up(y); lx[x]=rx[x]=lx[y]=rx[y]=;}
void push_cut(int x,int y){
acs(x); int l=lx[x],r=rx[x];
if(l==x&&r==y) lx[x]=rx[x]=;
else{
cut(x,y);
if(l&&r) link(l,r);
}
}
int main()
{
int k,x,w;
n=read(); m=read(); S=n+;
for(int i=;i<=S;i++) size[i]=;
for(int i=;i<=n;i++){
k=read(); sum[i]=k;
if(i+k<=||i+k>n) push_link(i,S);
else link(i,i+k);
}
for(int i=;i<=m;i++){
k=read();
if(k==) x=read(),mrt(S),printf("%d\n",push_ans(x));
else{
x=read(); w=read();
if(x+sum[x]<=||x+sum[x]>n) cut(x,S);
else push_cut(x,x+sum[x]);
if(x+w<=||x+w>n) push_link(x,S);
else link(x,x+w);
sum[x]=w;
}
}
return ;
}