BZOJ2002: Bounce flying sheep (LCT)

 

I used to solve this problem in blocks before, but recently I learned LCT, and found that it is also a template problem of LCT, so I did it with LCT.

Block solution: https://blog.csdn.net/f2935552941/article/details/78157052

 

For LCT, I recommend a blog, which is clear, but if you want to know more about it, you can find the paper of the national training team.

Recommended blog: https://blog.csdn.net/JeremyGJY/article/details/51078087

 

Solutions:

The specific problem is that we build a n edge for X and x+a[x]. If x+a[x] is greater than N, we can build it to n+1 by default. Then we query the number of times x jumps out, that is, we can pick out the chain from x to n+1, and the number of nodes on the chain is - 1.

If you want to modify it, you can use the normal edge deletion and edge creation,

I found a board of the big guy. I feel it's pretty good.

 

Ac Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int mod=1e9+7;
const int INF=1e9+7;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
int n,m,a[maxn];
struct LCT  //LCT template
{
    int father[maxn+5],son[maxn+5][2],si[maxn+5];
    bool flip[maxn+5];
    void init(){ for(int i=1;i<=n+1;i++) si[i]=1; }
    void Pushup(int p) {si[p]=si[son[p][0]]+1+si[son[p][1]];}
    void Add_flip(int p) {swap(son[p][0],son[p][1]);flip[p]^=1;}
    void Pushdown(int p)
    {
        if (!flip[p]) return;
        if (son[p][0]) Add_flip(son[p][0]);
        if (son[p][1]) Add_flip(son[p][1]);
        flip[p]=false;
    }
    bool is_ro(int p) {return p!=son[father[p]][0]&&p!=son[father[p]][1];}
    void Rotate(int p)
    {
        int fa=father[p],d=p==son[fa][0];
        if (!is_ro(fa)) son[father[fa]][fa==son[father[fa]][1]]=p;
        son[fa][d^1]=son[p][d];father[son[p][d]]=fa;son[p][d]=fa;
        Pushup(fa);Pushup(p);father[p]=father[fa];father[fa]=p;
    }
    int top,stk[maxn+5];
    void Splay(int p)
    {
        stk[++top]=p;
        for (int i=p;!is_ro(i);i=father[i]) stk[++top]=father[i];
        while (top) Pushdown(stk[top--]);
        while (!is_ro(p))
        {
            int fa=father[p];
            if (!is_ro(fa))
            {
                int d1=fa==son[father[fa]][1],d2=p==son[fa][1];
                if (d1==d2) Rotate(fa); else Rotate(p);
            }
            Rotate(p);
        }
    }
    void Access(int p)
    {
        int lst=0;
        while (p)
        {
            Splay(p);son[p][1]=lst;Pushup(p);
            lst=p;p=father[p];
        }
    }
    void make_ro(int p) {Access(p);Splay(p);Add_flip(p);}
    void Link(int x,int y) {Access(y);make_ro(y);father[y]=x;}
    void Cut(int x,int y)
    {
        make_ro(y);Access(x);Splay(x);
        father[y]=son[x][0]=0;Pushup(x);
    }
};
LCT tr;
int main()
{
    scanf("%d",&n); tr.init();  //Initialization
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),tr.Link(min(i+a[i],n+1),i);   //Build edge
    scanf("%d",&m);
    while(m--)
    {
        int flag,x,y;
        scanf("%d",&flag);
        if(flag==1)
        {
            scanf("%d",&x); x++;
            tr.make_ro(n+1);tr.Access(x);tr.Splay(x);
            printf("%d\n",tr.si[x]-1);
        }
        else 
        {
            scanf("%d%d",&x,&y); x++;
            tr.Cut(min(x+a[x],n+1),x),tr.Link(min(x+y,n+1),x);
            a[x]=y;
        }
    }
    //system("pause");
    return 0;
}

 

Posted by ritter on Wed, 01 Jan 2020 09:14:28 -0800