【Splay】[SGU 187]Twist and whirl - want to cheat

这道题真是我见过的最坑的平衡树的题目。。。。
time limit per test: 0.25 sec.
memory limit per test: 4096 KB
这个也太小了吧!
题目大意就是有一个数列一开始是1-n然后给出l, r每次把当前第l到第r个逆序,然后输出n<=130000 m<=2000
首先我写了一个传统的东西,然后在24组TLE然后,从指针的Splay转换成数组的Splay然后发现依然过不了,分析了一下复杂度,发现如果用传统的Splay的Insert虽然理论复杂度很低,但是相对于这道题,Insert完了之后整个树就退化成了一条链,然后根据这个题目的Insert特殊优化线段树的构建方法建树就可以A了
然后就是一开始整棵树里面有无限小和无限大,然后每次翻转的时候把l-1放到根节点,把r+1放到根节点的右儿子,然后给根节点的右儿子的左儿子打标记,然后要对该节点子树操作的时候向下传递标记,然后交换左右节点就行了

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 130013;
int ch[MAXN][2], fa[MAXN], val[MAXN], size[MAXN], ecnt, root;
bool rev[MAXN];
inline void Update(int x){size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;}
inline void push_up(int u){
    if(rev[u]){
        swap(ch[u][0], ch[u][1]);
        rev[ch[u][0]] ^= 1;
        rev[ch[u][1]] ^= 1;
        rev[u] = 0;
    }
}
inline void Rotate(int x, int d){
    int y = fa[x];
    ch[y][!d] = ch[x][d];
    fa[x] = fa[y];
    if(ch[x][d]!=0)
        fa[ch[x][d]] = y;
    if(fa[y]!=0)
        ch[fa[y]][y == ch[fa[y]][1]] = x;
    fa[y] = x;
    ch[x][d] = y;
    if(y == root) root = x;
    Update(y);
}
void Splay(int, int);
inline void Insert(int &now, int l, int r, int f){
    if(l > r) return ;
    now = ++ecnt;
    int mid = (l + r) >> 1;
    val[now] = mid, fa[now] = f;
    Insert(ch[now][0], l, mid-1, now);
    Insert(ch[now][1], mid+1, r, now);
    Update(now);
}
int f1, f2;
inline void Splay(int x,int y){
    while(fa[x] != y){
        f1 = fa[x]; f2 = fa[f1];
        if(f2 == y){
            push_up(f1);
            push_up(x);
            if(x == ch[f1][0]) Rotate(x,1);
            else Rotate(x,0);
        }else{
            push_up(f2);
            push_up(f1);
            push_up(x);
            if(f1 == ch[f2][0]){
                if(x == ch[f1][0]){
                    Rotate(f1, 1);
                    Rotate(x, 1);
                }else{
                    Rotate(x, 0);
                    Rotate(x, 1);
                }
            }else{
                if(x == ch[f1][0]){
                    Rotate(x, 1);
                    Rotate(x, 0);
                }else{
                    Rotate(f1, 0);
                    Rotate(x, 0);
                }
            }
        }
        Update(x);
    }
}
inline int Find_Rank(int va){
    int ret = root;
    while(true){
        push_up(ret);
        if(size[ch[ret][0]]+1 == va)
            break;
        if(va > size[ch[ret][0]])
                va -= size[ch[ret][0]] + 1, ret = ch[ret][1];
        else
            ret = ch[ret][0];
    }
    return ret;
}
int main(){
    int n, mode, modep, t, p, q;
    scanf("%d",&t);
    Insert(root, 0, t+1, 0);
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d", &mode, &modep);
        p = Find_Rank(mode);
        q = Find_Rank(modep+2);
        Splay(p, 0);
        Splay(q, p);
        rev[ch[q][0]] ^= 1;
    }
    printf("%d", val[Find_Rank(2)]);
    for(int i=2;i<=t;i++)
        printf(" %d", val[Find_Rank(i+1)]);

    return 0;
}

posted on 2015-06-11 13:57  JeremyGuo  阅读(182)  评论(0编辑  收藏  举报

导航