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

来源:互联网 发布:木地板品牌 知乎 编辑:程序博客网 时间:2024/06/05 18:35

这道题真是我见过的最坑的平衡树的题目。。。。
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;}
0 0
原创粉丝点击