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\n",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]);
        }
    }
}

 

posted @ 2015-09-28 16:15  qscqesze  阅读(361)  评论(0编辑  收藏  举报