SGU 187 Twist and whirl - want to cheat(splay)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=187

题意:给出一个长度为n的数列,每次将某个区间的数字翻转。求最后的序列。

思路:将数列两端增加两个哨兵,也就是现在有n+2个数,其中1到n映射到现在的2到n+1。对于每个区间[A,B],将A-1调整到根节点,将B+1调整到根节点的右子树,那么整个区间就到了根节点右子树的左子树(设该节点为P)。将P标记为翻转。每次查找时翻转标记向下传递,类似于线段树的那种操作。

#include <cstdio>

#include <cstring>

#include <iostream>

#include <algorithm>

using namespace std;



const int N=130005;

int n,m;

int c[N][2],p[N],s[N],sign[N];

int root;





void update(int f,int x,int flag)

{

    p[x]=f;

    if(!f) return;

    c[f][flag]=x;

    s[f]=1+s[c[f][0]]+s[c[f][1]];

}



void down(int x)

{

    if(!sign[x]) return;

    sign[x]=0;

    swap(c[x][0],c[x][1]);

    sign[c[x][0]]^=1;

    sign[c[x][1]]^=1;

}



void rotate(int x)

{

    int P=p[x],G=p[P];

    if(c[P][0]==x)

    {

        update(P,c[x][1],0);

        update(x,P,1);

        update(G,x,!(c[G][0]==P));

    }

    else

    {

        update(P,c[x][0],1);

        update(x,P,0);

        update(G,x,!(c[G][0]==P));

    }

}







void splay(int x,int &goal)

{

    int P=p[x],G=p[P],limit=p[goal];

    while(P!=limit)

    {

        if(G!=limit&&(c[G][0]==P)==(c[P][0]==x)) rotate(P);

        rotate(x);

        P=p[x];

        G=p[P];

    }

    goal=x;

    down(goal);

}



int select(int x)

{

    int t=root;

    while(1)

    {

        down(t);

        if(s[c[t][0]]+1==x) break;

        if(s[c[t][0]]+1>x) t=c[t][0];

        else x-=s[c[t][0]]+1,t=c[t][1];

    }

    return t;

}



int build(int L,int R)

{

    if(L>R) return 0;

    int m=(L+R)>>1;

    update(m,build(L,m-1),0);

    update(m,build(m+1,R),1);

    return m;

}



int main()

{

    scanf("%d%d",&n,&m);

    root=build(1,n+2);

    int A,B,i,r1,r2;

    while(m--)

    {

        scanf("%d%d",&A,&B);

        r1=select(A);

        r2=select(B+2);

        splay(r1,root);

        splay(r2,c[r1][1]);

        i=c[root][1];

        i=c[i][0];

        sign[i]^=1;

    }

    for(i=2;i<=n+1;i++) printf("%d ",select(i)-1);

    puts("");

    return 0;

}

  

你可能感兴趣的:(play)