bzoj2002 [Hnoi2010]Bounce flying sheep

Posted by Pezmc on Sun, 03 May 2020 10:04:44 +0200

Description

One day, Lostmonkey invented a super elastic device. In order to show off in front of his sheep friends, he invited the little sheep to play a game together. At the beginning of the game, Lostmonkey placed n devices along a straight line on the ground. Each device set the initial elastic coefficient ki. When the sheep reached the I device, it would play back ki steps to reach the i+ki device. If there was no i+ki device, the sheep would be bounced. The sheep wanted to know that when it started from the i-th device, it would be bounced off after being bounced several times. In order to make the game more interesting, Lostmonkey can modify the elasticity coefficient of a certain elastic device, which is a positive integer at any time.

20% data n, m < = 10000
100% data n < = 200000, m < = 100000

Solution

Another LCT naked question. After reading the question, my brain made up a moving tree-_-||
The distance from the point to the root is required here. Obviously, violent jumping is not allowed. Splay maintains the size of an interval. First access(x) and then rotate x to the root of splay to know the depth through the size of the left son of the root
It's said that it can be done in blocks

Code

#include <stdio.h>
#include <algorithm>
const int N=400005;
struct treeNode{int son[2],fa,lazy,size; bool is_root;}t[N];
int a[N],n;
void push_up(int x) {
    t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+1;
}
void push_down(int x) {
    if (!t[x].lazy||!x) return ;
    std:: swap(t[x].son[0],t[x].son[1]);
    t[t[x].son[0]].lazy^=1;
    t[t[x].son[1]].lazy^=1;
    t[x].lazy=0;
}
void rotate(int x) {
    if (t[x].is_root) return ;
    int y=t[x].fa; int z=t[y].fa;
    int k=t[y].son[1]==x;
    t[y].son[k]=t[x].son[!k];
    if (t[x].son[!k]) t[t[x].son[!k]].fa=y;
    t[x].son[!k]=y;
    t[y].fa=x;
    t[x].fa=z;
    if (t[y].is_root) {
        t[x].is_root=1;
        t[y].is_root=0;
    } else t[z].son[t[z].son[1]==y]=x;
    push_up(y);
    push_up(x);
}
void remove(int x) {
    if (!t[x].is_root) remove(t[x].fa);
    push_down(x);
}
void splay(int x) {
    remove(x);
    while (!t[x].is_root) {
        int y=t[x].fa; int z=t[y].fa;
        if (!t[y].is_root) {
            if ((t[y].son[1]==x)^(t[z].son[1]==y)) rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
}
void access(int x) {
    int y=0;
    do {
        splay(x);
        t[t[x].son[1]].is_root=1;
        t[t[x].son[1]=y].is_root=0;
        push_up(x);
        y=x; x=t[x].fa;
    } while (x);
}
void mroot(int x) {
    access(x); splay(x);
    t[x].lazy^=1;
}
void link(int x,int y) {
    if (y>n) y=n+1;
    mroot(x); t[x].fa=y;
    splay(x);
}
void cut(int x,int y) {
    if (y>n) y=n+1;
    mroot(x); access(y); splay(y);
    t[t[y].son[0]].is_root=1;
    t[t[y].son[0]].fa=0;
    t[y].son[0]=0;
    push_up(y);
}
int query(int x) {
    mroot(n+1);
    access(x); splay(x);
    return t[t[x].son[0]].size;
}
int main(void) {
    scanf("%d",&n);
    for (int i=1;i<=n+1;i++) t[i].is_root=t[i].size=1;
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<=n;i++) {
        if (i+a[i]>n) link(i,n+1);
        else link(i,i+a[i]);
    }
    int m; scanf("%d",&m);
    while (m--) {
        int opt,x; scanf("%d%d",&opt,&x); x++;
        if (opt==1) {
            printf("%d\n", query(x));
        } else {
            int y; scanf("%d",&y);
            cut(x,x+a[x]);
            a[x]=y;
            link(x,x+a[x]);
        }
    }
    return 0;
}