「CF13E」Holes【LCT】

題目連接

題意

  • BZOJ2002基本是一樣的,就是多了求出最後彈出的位置

題解

  • 注意splitsplit後找父親的時候一定要push_downpush\_down就行了

代碼

#include<bits/stdc++.h>

using namespace std;
const int maxn=2e5+10;
#define inf 0x3f3f3f3f

namespace LCT{
    int ch[maxn][2],fa[maxn],mark[maxn];
    int val[maxn],siz[maxn];
    inline bool not_root(int x) {return ch[fa[x]][0]==x||ch[fa[x]][1]==x;}
    inline int dir(int x) {return ch[fa[x]][1]==x;}
    inline void add_mark(int x) {swap(ch[x][0],ch[x][1]);mark[x]^=1;}        //將x這顆子樹翻轉
    inline void push_down(int x) {
        if(mark[x]) {
            if(ch[x][0]) add_mark(ch[x][0]);
            if(ch[x][1]) add_mark(ch[x][1]); 
            mark[x]=0;
        }
    }
    inline void push_up(int x) {
        siz[x]=1;
        if(ch[x][0]) siz[x]+=siz[ch[x][0]];
        if(ch[x][1]) siz[x]+=siz[ch[x][1]];   
    }
    inline void pushall(int x) {
        if(not_root(x)) pushall(fa[x]);
        push_down(x);
    }
    inline void rotate(int x){
        int y=fa[x],z=fa[y],k=dir(x);
        if(ch[x][k^1]) fa[ch[x][k^1]]=y;ch[y][k]=ch[x][k^1];
        if(not_root(y)) ch[z][dir(y)]=x;fa[x]=z;
        ch[x][k^1]=y;fa[y]=x;
        push_up(y);
    }
    inline void splay(int x,int goal=0) {
        pushall(x);
        while(not_root(x)) {
            int y=fa[x],z=fa[y];
            if(not_root(y)) {
                if(dir(x)==dir(y)) rotate(y);
                else rotate(x);
            }
            rotate(x);
        }
        push_up(x);
    }
    inline void access(int x) {    //從原樹的根向x拉一條實鏈
        for(int y=0;x;y=x,x=fa[x]) {
            splay(x);ch[x][1]=y;push_up(x);
        }
    }
    inline void make_root(int x) {  //使x成爲原樹的根
        access(x);splay(x);add_mark(x);
    }
    inline int find_root(int x) {   //找到x在原樹中的根
        access(x);splay(x);
        while(ch[x][0]) push_down(x),x=ch[x][0];
        splay(x);
        return x;
    }
    inline void split(int x,int y) {   //拉出一條x->y的實鏈,y爲splay根
        make_root(x);access(y);splay(y);
    }
    inline bool link(int x,int y) {    //連接x與y,若已經在同一顆原樹中,返回0
        make_root(x);
        if(find_root(y)==x) return 0;
        fa[x]=y;return 1;
    } 
    inline bool cut(int x,int y) {
        make_root(x);
        if(find_root(y)!=x||fa[y]!=x||ch[y][0]) return 0;
        fa[y]=ch[x][1]=0;
        push_up(x);
        return 1;
    }
};
using namespace LCT;

int n,m,opt,a[maxn],x,y;
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
        if(i+a[i]<=n) link(i,i+a[i]);
        else link(i,n+1);
    }
    for(int i=1;i<=m;i++) {
        scanf("%d",&opt);
        if(opt==1) {
            scanf("%d",&x);
            split(x,n+1);
            int k=ch[n+1][0];
            while(ch[k][1]) push_down(k),k=ch[k][1];  //注意下放標記
            printf("%d %d\n",k,siz[n+1]-1);
        }else {
            scanf("%d %d",&x,&y);
            if(x+a[x]<=n) cut(x+a[x],x);
            else cut(n+1,x);
            a[x]=y;
            if(x+a[x]<=n) link(x+a[x],x);
            else link(n+1,x);
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章