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; 
} 

转载于:https://www.cnblogs.com/sssy/p/8982785.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值