UVA11922 Permutation Transformer

Permutation Transformer

Write a program to transform the permutation 1, 2, 3,..., n according to m instructions. Each instruction (a, b) means to take out the subsequence from the a-th to the b-th element, reverse it, then append it to the end.
Input
There is only one case for this problem. The first line contains two integers n and m ( 1$ \le$n, m$ \le$100, 000). Each of the next m lines contains an instruction consisting of two integers a and b ( 1$ \le$a$ \le$b$ \le$n).
Output
Print n lines, one for each integer, the final permutation.

Explanation of the sample below
Instruction (2,5): Take out the subsequence {2,3,4,5}, reverse it to {5,4,3,2}, append it to the remaining permutation {1,6,7,8,9,10}
Instruction (4,8): The subsequence from the 4-th to the 8-th element of {1,6,7,8,9,10,5,4,3,2} is {8,9,10,5,4}. Take it out, reverse it, and you'll get the sample output.

Warning: Don't use cin, cout for this problem, use faster i/o methods e.g scanf, printf.
Sample Input
10 2
2 5
4 8
Sample Output
1
6
7
3
2
4
5
10
9

8


题意:有n个数m条指令,每条指令时要求你取出一段[a,b],将它翻转然后添加到序列最后。。。

伸展树的合并与拆分,多加两个结点0和n+1,然后对每个查询都把树进行拆分,拆成0-a-1(从0开始所以实际上是a),对b就对刚刚拆分的右子树再进行拆分。。。然后反转合并就是了,这里因为多了两个结点,所以注意合并的时候不要把多的结点合并进去,这两个结点应该都始终在两端。。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=100010;
struct Node
{
    Node *ch[2];
    int v;
    int s;
    int flip;
    Node(int v):v(v){ch[0]=ch[1]=NULL,s=1,flip=0;}
    int cmp(int x)
    {
        int t=(ch[0]==NULL)?0:ch[0]->s;
        if(t>=x)
            return 0;
        else if(t+1==x)
            return -1;
        return 1;
    }
    void maintain()
    {
        s=1;
        if(ch[1]!=NULL)
            s+=ch[1]->s;
        if(ch[0]!=NULL)
            s+=ch[0]->s;
    }
    void pushdown()
    {
        if(flip)
        {
            flip=0;
            swap(ch[0],ch[1]);
            if(ch[0]!=NULL)
                ch[0]->flip^=1;
            if(ch[1]!=NULL)
                ch[1]->flip^=1;
        }
    }
};
void rotate(Node* &root,int d)
{
    Node *k=root->ch[d^1]; root->ch[d^1]=k->ch[d]; k->ch[d]=root;
    root->maintain(); k->maintain(); root=k;
}
void splay(Node* &root,int k)
{
    root->pushdown();
    int d=root->cmp(k);
    if(d==1)
    {
        if(root->ch[0]!=NULL)
            k-=root->ch[0]->s;
        k--;
    }
    if(d!=-1)
    {
        Node *p=root->ch[d];
        p->pushdown();
        int d2=p->cmp(k);
        int k2=k;
        if(d2==1)
        {
            if(p->ch[0]!=NULL)
                k2-=p->ch[0]->s;
            k2--;
        }
        if(d2!=-1)
        {
            splay(p->ch[d2],k2);
            if(d==d2)
                rotate(root,d^1);
            else
                rotate(root->ch[d],d);
        }
        rotate(root,d^1);
    }
}
Node *merge(Node *left,Node *right)
{
    splay(left,left->s);
    left->ch[1]=right;
    left->maintain();
    return left;
}
void split(Node *root,int k,Node* &left,Node* &right)
{
    splay(root,k);
    left=root;
    right=root->ch[1];
    root->ch[1]=NULL;
    left->maintain();
}
void build(Node* &root,int l,int r)
{
    int mid=(l+r)>>1;
    root=new Node(mid);
    if(l<mid)
        build(root->ch[0],l,mid-1);
    if(r>mid)
        build(root->ch[1],mid+1,r);
    root->maintain();
}
int n,m;
void dfs(Node *ans)
{
    ans->pushdown();
    if(ans->ch[0]!=NULL)
        dfs(ans->ch[0]);
    if(ans->v!=0&&ans->v!=n+1)
        printf("%d\n",ans->v);
    if(ans->ch[1]!=NULL)
        dfs(ans->ch[1]);
}
void deletetree(Node *cur)
{
    if(cur->ch[0]!=NULL)
        deletetree(cur->ch[0]);
    if(cur->ch[1]!=NULL)
        deletetree(cur->ch[1]);
    delete cur;
}
Node *root;
int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        root=NULL;
        build(root,0,n+1);
        int a,b;
        while(m--)
        {
            scanf("%d%d",&a,&b);
            Node *left,*mid,*right,*o,*tmp;
            split(root,a,left,o);
            split(o,b-a+1,mid,right);
            if (right->s-1>0)
            {
                split(right,right->s-1,tmp,o);
                mid->flip^=1;
                root=merge(left,merge(merge(tmp,mid),o));
            }
            else
            {
                mid->flip^=1;
                root=merge(left,merge(mid,right));
            }
        }
        dfs(root);
        deletetree(root);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值