P3203 [HNOI2010] 弹飞绵羊

P3203 [HNOI2010] 弹飞绵羊

题目描述

某天,Lostmonkey 发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。

游戏一开始,Lostmonkey 在地上沿着一条直线摆上 \(n\) 个装置,每个装置设定初始弹力系数 \(k_i\),当绵羊达到第 \(i\) 个装置时,它会往后弹 \(k_i\) 步,达到第 \(i+k_i\) 个装置,若不存在第 \(i+k_i\) 个装置,则绵羊被弹飞。

绵羊想知道当它从第 \(i\) 个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey 可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

输入格式

第一行包含一个整数 \(n\),表示地上有 \(n\) 个装置,装置的编号从 \(0 \sim n-1\)

接下来一行有 \(n\) 个正整数,依次为那 \(n\) 个装置的初始弹力系数。

第三行有一个正整数 \(m\),表示操作次数。接下来 \(m\) 行每行至少有两个数 \(i,j\)

  • \(i=1\),你要输出从编号为 \(j\) 的装置出发被弹几次后被弹飞

  • \(i=2\),则还会再输入一个正整数 \(k\),表示编号为 \(j\) 的弹力装置的系数被修改成 \(k\)

输出格式

对于每个 \(i=1\) 的操作,输出一行一个整数表示答案。

【数据范围】

对于 \(100\%\) 的数据,\(1\le n \le 2\times 10^5\)\(1\le m \le 10^5\)

Solution:

LD再不放假让你飞起来

没想到这种题目还能用 LCT 做。我们思考一下每次重设弹力系数相当于什么:相当于断掉原来的边然后连一条 (x,x+k) 的边。所以我们开始时将每个点到对应的“着陆点”上就好了,然后注意一下因为弹飞显然是单向的,所有我们只需要让 \(x\) 认父就好了,并不需要像原来的 link 一样。然后查询就直接 access 然后 splay 就好了。我们甚至都不需要换根(显然,因为没有查询两个点的路径的需求)。

然后这道看起来很模拟的 LCT 就被我们愉快的做完了。

Code:

#include<bits/stdc++.h>
const int N=2e5+5;
using namespace std;
int n,m;
struct LCT{
    struct Tree{
        int tag,ff,ch[2],siz;
    }t[N<<2];
    int st[N];
    #define ls t[x].ch[0]
    #define rs t[x].ch[1]
    #define fa t[x].ff
    inline bool isroot(int x)
    {
        return (t[fa].ch[0]==x||t[fa].ch[1]==x);
    }
    inline void pushup(int x)
    {
        t[x].siz=t[ls].siz+t[rs].siz+1;
    }
    inline void rotate(int x)
    {
        int y=fa,z=t[fa].ff,k=t[fa].ch[1]==x ? 1 : 0;
        if(isroot(y))t[z].ch[t[z].ch[1]==y]=x;
        t[x].ff=z;

        t[y].ch[k]=t[x].ch[!k];
        if(t[x].ch[!k])t[t[x].ch[!k]].ff=y;

        t[x].ch[!k]=y;
        t[y].ff=x;
        pushup(y);
    }
    inline void splay(int x)
    {
        int y=x,z=0;
        while(isroot(x))
        {
            y=fa,z=t[fa].ff;
            if(isroot(y)){rotate((t[y].ch[1]==x)==(t[z].ch[1]==y) ? y : x);}
            rotate(x);
        }
        pushup(x);
    }
    void access(int x)
    {
        int y=0;
        while(x)
        {
            splay(x);rs=y;pushup(x);
            y=x;x=fa;
        }
    }
    void link(int x,int y)
    {
        if(y<=n){t[x].ff=y;pushup(x);}
    }
    void cut(int x) // 这里是减去一个点 x
    {
        access(x),splay(x);
        t[x].ch[0]=t[ls].ff=0;
    }
    int query(int x)
    {
        access(x);splay(x);
        return t[x].siz;
    }
}T;
void work()
{
    cin>>n;
    for(int i=1,tmp;i<=n;i++)
    {
        scanf("%d",&tmp);
        T.t[i].siz=1;
        T.link(i,i+tmp);
    }
    cin>>m;
    for(int i=1,opt,x,y;i<=m;i++)
    {
        scanf("%d%d",&opt,&x);
        x++;
        if(opt&1)
        {
            int ans=T.query(x);
            printf("%d\n",ans);
        }
        else
        {
            scanf("%d",&y);
            T.cut(x);
            T.link(x,x+y);
        }
    }
}
int main()
{
    //freopen("bounce.in","r",stdin);freopen("bounce.out","w",stdout);
    work();
    return 0;
}
posted @ 2025-01-24 16:31  liuboom  阅读(21)  评论(0)    收藏  举报