• BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 LCT


    2002: [Hnoi2010]Bounce 弹飞绵羊

    Time Limit: 1 Sec  

    Memory Limit: 256 MB

    题目连接

    http://www.lydsy.com/JudgeOnline/problem.php?id=2002

    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

    HINT

    题意

    有link操作,cut操作,查询子树大小

    题解:

    动态树裸题……

    其实就是查询子树大小啦

    连边过去就吼了

    代码:

    //qscqesze
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <bitset>
    #include <vector>
    #include <sstream>
    #include <queue>
    #include <typeinfo>
    #include <fstream>
    #include <map>
    #include <stack>
    typedef long long ll;
    using namespace std;
    //freopen("D.in","r",stdin);
    //freopen("D.out","w",stdout);
    #define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
    #define maxn 200500
    #define mod 1000000007
    #define eps 1e-9
    #define e exp(1.0)
    #define PI acos(-1)
    #define lowbit(x) (x)&(-x)
    const double EP  = 1E-10 ;
    int Num;
    //const int inf=0x7fffffff;
    const ll inf=999999999;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    //*************************************************************************************
    
    const int MAXN = 200500;
    struct Node {
        Node *ch[2], *p; int size, value;
        bool rev;
        Node(int t = 0);
        inline bool dir(void) {return p->ch[1] == this;}
        inline void SetC(Node *x, bool d) {
            ch[d] = x; x->p = this;
        }
        inline void Rev(void) {
            swap(ch[0], ch[1]); rev ^= 1;
        }
        inline void Push(void) {
            if (rev) {
                ch[0]->Rev();
                ch[1]->Rev();
                rev = 0;
            }
        }
        inline void Update(void) {
            size = ch[0]->size + ch[1]->size + 1;
        }
    }Tnull, *null = &Tnull, *fim[MAXN];
    // 要记得额外更新null的信息
    Node::Node(int _value){ch[0] = ch[1] = p = null; rev = 0;}
    inline bool isRoot(Node *x) {return x->p == null || (x != x->p->ch[0] && x != x->p->ch[1]);}
    inline void rotate(Node *x) {
        Node *p = x->p; bool d = x->dir();
        p->Push(); x->Push();
        if (!isRoot(p)) p->p->SetC(x, p->dir()); else x->p = p->p;
        p->SetC(x->ch[!d], d);
        x->SetC(p, !d);
        p->Update();
    }
    inline void splay(Node *x) {
        x->Push();
        while (!isRoot(x)) {
            if (isRoot(x->p)) rotate(x);
            else {
                if (x->dir() == x->p->dir()) {rotate(x->p); rotate(x);}
                else {rotate(x); rotate(x);}
            }
        }
        x->Update();
    }
    inline Node* Access(Node *x) {
        Node *t = x, *q = null;
        for (; x != null; x = x->p) {
            splay(x); x->ch[1] = q; q = x;
        }
        splay(t); //info will be updated in the splay;
        return q;
    }
    inline void Evert(Node *x) {
        Access(x); x->Rev();
    }
    inline void link(Node *x, Node *y) {
        Evert(x); x->p = y;
    }
    inline Node* getRoot(Node *x) {
        Node *tmp = x;
        Access(x);
        while (tmp->Push(), tmp->ch[0] != null) tmp = tmp->ch[0];
        splay(tmp);
        return tmp;
    }
    // 一定要确定x和y之间有边
    inline void cut(Node *x, Node *y) {
        Access(x); splay(y);
        if (y->p != x) swap(x, y);
        Access(x); splay(y);
        y->p = null;
    }
    inline Node* getPath(Node *x, Node *y) {
        Evert(x); Access(y);
        return y;
    }
    inline void clear(void) {
        null->rev = 0; null->size = 0; null->value = 0;
    }
    int a[maxn];
    int main()
    {
        clear();
        int n=read();
        for(int i=0;i<=n+1;i++)
            fim[i] = new Node();
        for(int i=1;i<=n;i++)
            a[i]=read();
        for(int i=1;i<=n;i++)
        {
            int p = i+a[i];
            if(p>n)p=n+1;
            link(fim[i],fim[p]);
        }
        int m = read();
        while(m--)
        {
            int op = read();
            if(op == 1)
            {
                int x = read();
                x++;
                Access(fim[x]);
                splay(fim[x]);
                printf("%d
    ",fim[x]->size - 1);
            }
            else
            {
                int x=read(),y=read();
                x++;
                int p = x+a[x];
                if(p>n)p=n+1;
                cut(fim[x],fim[p]);
                a[x]=y;
                p = x+a[x];
                if(p>n)p=n+1;
                link(fim[x],fim[p]);
            }
        }
    }
  • 相关阅读:
    c语言进阶2-变量的作用域与无参函数
    《Linux 性能及调优指南》3.2 CPU瓶颈
    《Linux 性能及调优指南》3.1 确认瓶颈
    马哥Linux base学习笔记
    《Linux 性能及调优指南》1.6 了解Linux性能指标
    Linux性能及调优指南1.2之Linux内存架构
    《Linux 性能及调优指南》1.1 Linux进程管理
    分布式系统的Raft算法
    《马哥出品高薪linux运维教程》wingkeung学习笔记-linux基础入门课程
    Systemd 入门教程:实战篇
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4844282.html
Copyright © 2020-2023  润新知