bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊
题解
跳出序构成一颗一n +1为根的树
你需要支持cut,link,以及查询子树大小的操作
lct随便打......
话说之前是用块状链表水的....
代码
#include<cstdio>
#include<algorithm>
const int maxn = 200007;
inline int read() {
int x = 0 ,f = 1;
char c = getchar();
while(c < '0' || c > '9' ){ if(c == '-')f = -1;c = getchar();}
while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar();
return x * f;
}
int a[maxn];
int ch[maxn][2];
int siz[maxn],fa[maxn];
int rev[maxn];
bool isroot(int x) {return ch[fa[x]][0] != x && ch[fa[x]][1] != x;}
inline int ident(int x) {return x == ch[fa[x]][1] ? 1 : 0;}
inline void update(int x) {siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;}
inline void connect(int x,int f,int which) {ch[f][which] = x;fa[x] = f;}
void push_down(int x) { if(rev[x]) rev[x] = 0,std::swap(ch[x][0],ch[x][1]), rev[ch[x][0]] ^= 1,rev[ch[x][1]] ^= 1; }
void rotate(int x) {
int y = fa[x],z = fa[y],yson = ident(x),zson = ident(y);
int xson = ch[x][yson ^ 1];
fa[x] = z;
if(!isroot(y)) connect(x,z,zson);
connect(xson,y,yson);
connect(y,x,yson ^ 1);
update(x),update(y);//update(z);
}
int stack[maxn],top = 0;
void splay (int x) {
stack[++ top] = x;
for(int i = x;!isroot(i);i = fa[i]) stack[++ top] = fa[i];
while(top) push_down(stack[top --]);
while(!isroot(x)) {
int y = fa[x],z = fa[y];
if(!isroot(y)) {
if(ch[y][0] == x ^ ch[z][0] == y) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x) {for(int i = 0;x;x = fa[i = x]) splay(x),ch[x][1] = i,update(x);}
void makeroot(int x) { access(x),splay(x);rev[x] ^= 1; return; }
void link(int x,int y) { makeroot(x); fa[x] = y;return splay(x); }
void split(int x,int y) { makeroot(x) , access(y); return splay(y); }
void cut(int x,int y) { split(x,y); ch[y][0] = fa[ch[y][0]] = 0; return ; }
int query(int x,int y) { split(x,y); return siz[ch[y][0]]; }
int n,to[maxn];
int main() {
n = read();
for(int i = 1;i <= n;++ i) {
a[i] = read();
to[i] = fa[i] = i + a[i] > n ? n + 1 : i + a[i];
siz[i] = 1;
}
int k = read();
for(int a,b,c;k --;) {
a = read();
if(a == 1) {
b = read() + 1;
printf("%d\n",query(n + 1, b));
}
else {
b = read() + 1,c = read();
cut(b,to[b]); link(b,to[b] = b + c > n ? n + 1 : b + c);
}
}
return 0;
}