zoukankan      html  css  js  c++  java
  • BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 [LCT]

    2002: [Hnoi2010]Bounce 弹飞绵羊

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 9156  Solved: 4701
    [Submit][Status][Discuss]

    Description

    某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

    Input

    第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

    Output

    对于每个i=1的情况,你都要输出一个需要的步数,占一行。

    Sample Input

    4
    1 2 1 1
    3
    1 1
    2 1 1
    1 1

    Sample Output

    2
    3

    i与min(i+k,n+1)连边,用LCT维护
    几次弹飞就是j到n+1的路径上几个点,MakeRoot(n+1)然后Access splay x之后x到n+1的路径就是x所在Atree的左子树
     
    注意:update维护size别忘+1
    Link不需要Access splay y只要连就行了...............当然这样也没错只是有点慢
     
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define pa t[x].fa
    #define lc t[x].ch[0]
    #define rc t[x].ch[1]
    const int N=3e4+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    struct node{
        int ch[2],fa,rev;
        int sum,w;
    }t[N];
    inline void update(int x){t[x].sum=t[lc].sum+t[rc].sum+t[x].w;}
    inline int wh(int x){return t[pa].ch[1]==x;}
    inline int isRoot(int x){return t[pa].ch[0]!=x&&t[pa].ch[1]!=x;}
    inline void pushDown(int x){
        if(t[x].rev){
            t[lc].rev^=1;
            t[rc].rev^=1;
            swap(lc,rc);
            t[x].rev=0;
        }
    }
    inline void rotate(int x){
        int f=t[x].fa,g=t[f].fa,c=wh(x);
        if(!isRoot(f)) t[g].ch[wh(f)]=x;t[x].fa=g;
        t[f].ch[c]=t[x].ch[c^1];t[t[f].ch[c]].fa=f;
        t[x].ch[c^1]=f;t[f].fa=x;
        update(f);update(x);
    }
    int st[N],top;
    inline void splay(int x){
        top=0;st[++top]=x;
        for(int i=x;!isRoot(i);i=t[i].fa) st[++top]=t[i].fa;
        for(int i=top;i>=1;i--) pushDown(st[i]);
        
        for(;!isRoot(x);rotate(x))
            if(!isRoot(pa)) rotate(wh(x)==wh(pa)?pa:x);
    }
    
    inline void Access(int x){
        for(int y=0;x;y=x,x=pa){
            splay(x);
            rc=y;
        }
    }
    inline void MakeRoot(int x){
        Access(x);
        splay(x);
        t[x].rev^=1;
    }
    inline int FindRoot(int x){
        Access(x);
        splay(x);
        while(lc) x=lc;
        return x;
    }
    inline void Link(int x,int y){
        MakeRoot(x);
        t[x].fa=y;
        splay(x);
    }
    inline void Cut(int x,int y){
        MakeRoot(x);
        Access(y);splay(y);
        t[y].ch[0]=t[x].fa=0;
    }
    int n,Q,x,y;
    char s[N];
    int main(){
        //freopen("in.txt","r",stdin);
        n=read();
        for(int i=1;i<=n;i++) t[i].w=t[i].sum=read();
        Q=read();
        while(Q--){
            scanf("%s",s);x=read();y=read();
            if(s[0]=='b'){
                if(FindRoot(x)==FindRoot(y)) puts("no");
                else puts("yes"),Link(x,y);
            }else if(s[0]=='p'){
                t[x].w=y;
                Access(x);splay(x);
            }else{
                if(FindRoot(x)!=FindRoot(y)) puts("impossible");
                else{
                    MakeRoot(x);Access(y);splay(y);
                    printf("%d
    ",t[y].sum);
                }
            }
        }
    }
     
     
  • 相关阅读:
    锁相环(PLL)的IP核调取及应用详解
    进阶项目(3)UART串口通信程序设计讲解
    基础项目(2)二选一数据选择器的设计
    读写储存器RAM IP核的调取及应用
    进阶项目(1)字符状态机讲解
    基础项目(1) 流水灯项目讲解
    只读储存器ROM IP核的调取及应用
    常见的关系运算符(移位运算符)
    常见的关系运算符(缩减运算符)
    乱七八糟
  • 原文地址:https://www.cnblogs.com/candy99/p/6273710.html
Copyright © 2011-2022 走看看