BZOJ2002:Bounce 弹飞绵羊(LCT)

版权声明:谁他喵没事儿会转我的博客啊QAQ,有没有人看都是一回事儿。。。 https://blog.csdn.net/f2935552941/article/details/82115697

之前用分块解过这道题,不过最近学到了LCT,发现它也是LCT的模板题,就用LCT做了一下。

分块解法:https://blog.csdn.net/f2935552941/article/details/78157052

LCT的话,推荐一篇博客,讲的比较清楚,但是如果想深入了解的话建议可以找国家集训队的论文看一下。

推荐博客:https://blog.csdn.net/JeremyGJY/article/details/51078087

解题思路:

这道题目具体就是我们对于 x 和 x+a[x] 建立一条边,如果 x+a[x] 大于 n,就默认建到 n+1 即可,之后查询 x 跳出次数,就是把 x 到 n+1 的链挑出来,这条链上的结点数-1 即可。

修改的话就用正常的删边和建边实现即可,

发现了大佬的一个板子,感觉还挺不错的。

Ac代码:

#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模板
{
    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();  //初始化
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),tr.Link(min(i+a[i],n+1),i);   //建边
    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;
}

猜你喜欢

转载自blog.csdn.net/f2935552941/article/details/82115697