关闭

HDU 3487 Play with Chain(Splay 经典操作)

202人阅读 评论(0) 收藏 举报
分类:

Play with Chain

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5770    Accepted Submission(s): 2334


Problem Description
YaoYao is fond of playing his chains. He has a chain containing n diamonds on it. Diamonds are numbered from 1 to n.
At first, the diamonds on the chain is a sequence: 1, 2, 3, …, n.
He will perform two types of operations:
CUT a b c: He will first cut down the chain from the ath diamond to the bth diamond. And then insert it after the cth diamond on the remaining chain.
For example, if n=8, the chain is: 1 2 3 4 5 6 7 8; We perform “CUT 3 5 4”, Then we first cut down 3 4 5, and the remaining chain would be: 1 2 6 7 8. Then we insert “3 4 5” into the chain before 5th diamond, the chain turns out to be: 1 2 6 7 3 4 5 8.

FLIP a b: We first cut down the chain from the ath diamond to the bth diamond. Then reverse the chain and put them back to the original position.
For example, if we perform “FLIP 2 6” on the chain: 1 2 6 7 3 4 5 8. The chain will turn out to be: 1 4 3 7 6 2 5 8

He wants to know what the chain looks like after perform m operations. Could you help him?
 

Input
There will be multiple test cases in a test data.
For each test case, the first line contains two numbers: n and m (1≤n, m≤3*100000), indicating the total number of diamonds on the chain and the number of operations respectively.
Then m lines follow, each line contains one operation. The command is like this:
CUT a b c // Means a CUT operation, 1 ≤ a ≤ b ≤ n, 0≤ c ≤ n-(b-a+1).
FLIP a b    // Means a FLIP operation, 1 ≤ a < b ≤ n.
The input ends up with two negative numbers, which should not be processed as a case.
 

Output
For each test case, you should print a line with n numbers. The ith number is the number of the ith diamond on the chain.
 

Sample Input
8 2 CUT 3 5 4 FLIP 2 6 -1 -1
 

Sample Output
1 4 3 7 6 2 5 8

【解题方法】Splay的经典操作了。区间翻转+复制粘贴。

【AC 代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 300005;
#define Key_value ch[ch[root][1]][0]
int n,q;
int size[maxn],pre[maxn],key[maxn],num[maxn],rev[maxn];
int ch[maxn][2],tot,root;
inline void newnode(int &r,int k,int father)
{
    r=++tot;
    ch[r][0]=ch[r][1]=0;
    pre[r]=father;
    rev[r]=0;
    key[r]=k;
}
inline void pushup(int r)
{
    size[r]=size[ch[r][0]]+size[ch[r][1]]+1;
}
void pushdown(int r)
{
    if(rev[r])
    {
        swap(ch[r][0],ch[r][1]);
        rev[ch[r][0]]^=1;
        rev[ch[r][1]]^=1;
        rev[r]=0;
    }
}
void Build(int &r,int L,int R,int father)
{
    if(L>R) return ;
    int mid=(L+R)/2;
    newnode(r,mid,father);
    Build(ch[r][0],L,mid-1,r);
    Build(ch[r][1],mid+1,R,r);
    pushup(r);
}
void init()
{
    tot=root=0;
    ch[root][0]=ch[root][1]=pre[root]=rev[root]=size[root]=0;
    newnode(root,-1,0);
    newnode(ch[root][1],-1,root);
    size[root]=2;
    Build(Key_value,1,n,ch[root][1]);
    pushup(ch[root][1]);
    pushup(root);
}
void Rotate(int x,int kind)
{
    int y=pre[x];
    pushdown(y);
    pushdown(x);
    ch[y][!kind]=ch[x][kind];
    pre[ch[x][kind]]=y;
    if(pre[y])
        ch[pre[y]][ch[pre[y]][1]==y]=x;
    pre[x]=pre[y];
    ch[x][kind]=y;
    pre[y]=x;
    pushup(y);
}
void Splay(int r,int goal)
{
    pushdown(r);
    while(pre[r]!=goal)
    {
        if(pre[pre[r]]==goal)
        {
            Rotate(r,ch[pre[r]][0]==r);
            pushdown(pre[r]);
            pushdown(r);
        }
        else{
            pushdown(pre[pre[r]]);
            pushdown(pre[r]);
            pushdown(r);
            int y=pre[r];
            int kind=(ch[pre[y]][0]==y);
            if(ch[y][kind]==r)
            {
                Rotate(r,!kind);
                Rotate(r,kind);
            }
            else{
                Rotate(y,kind);
                Rotate(r,kind);
            }
        }
    }
    pushup(r);
    if(goal==0) root=r;
}
int get_Kth(int r,int k)
{
    pushdown(r);
    int t=size[ch[r][0]];
    if(t==k-1) return r;
    if(t>=k) return get_Kth(ch[r][0],k);
    else return get_Kth(ch[r][1],k-t-1);
}
int get_Min(int r)
{
    pushdown(r);
    while(ch[r][0])
    {
        r=ch[r][0];
        pushdown(r);
    }
    return r;
}
int get_Max(int r)
{
    pushdown(r);
    while(ch[r][1])
    {
        r=ch[r][1];
        pushdown(r);
    }
    return r;
}
void Reversal(int a,int b)
{
    int x=get_Kth(root,a);
    int y=get_Kth(root,b+2);
    Splay(x,0);
    Splay(y,root);
    rev[Key_value]^=1;
}
void cut(int a,int b,int c)
{
    int x=get_Kth(root,a);
    int y=get_Kth(root,b+2);
    Splay(x,0);
    Splay(y,root);
    int tmp=Key_value;
    Key_value=0;
    pushup(ch[root][1]);
    pushup(root);
    int z=get_Kth(root,c+1);
    Splay(z,0);
    int m=get_Min(ch[root][1]);
    Splay(m,root);
    Key_value=tmp;
    pre[Key_value]=ch[root][1];
    pushup(ch[root][1]);
    pushup(root);
}
int cnt;
void Inorder(int r)
{
    if(r==0) return ;
    pushdown(r);
    Inorder(ch[r][0]);
    if(cnt>=1&&cnt<=n)
    {
        if(cnt>1) printf(" ");
        printf("%d",key[r]);
    }
    cnt++;
    Inorder(ch[r][1]);
}

int main()
{
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        if(n==-1&&q==-1) break;
        init();
        while(q--)
        {
            char op[10];
            scanf("%s",op);
            if(op[0]=='C')
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                cut(a,b,c);
            }
            else
            {
                int a,b;
                scanf("%d%d",&a,&b);
                Reversal(a,b);
            }
        }
        cnt=0;
        Inorder(root);
        printf("\n");
    }
    return 0;
}


0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

HDU3487(splay区间翻转+区间切割)

F - Play with Chain Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d &am...
  • u013268685
  • u013268685
  • 2014-11-24 01:31
  • 1616

Splay tree 区间翻转 模板

Splay作为二叉平衡树与其他二叉平衡树不同的是,Splay能够支持区间操作。最然可持续化Treap也可以做到,但是代码量实在是难以同日而语。 放一个模板,只支持区间翻转。想看其他操作的可以看我的 ...
  • jiangyuze831
  • jiangyuze831
  • 2014-09-06 20:19
  • 1082

RADOS:一种可扩展高可用的PB级存储集群(Ceph)

把Ceph的基础论文RADOS的原理介绍的前部分翻译了一下,与大家分享 ------------------------------------------------- 摘要 基于对象的存储架...
  • user_friendly
  • user_friendly
  • 2013-08-05 15:54
  • 2057

【HDU】3487 Play with Chain 【splay】

传送门:【HDU】3487 Play with Chain 题目分析:题目不难,注意细节就好,涉及到splay的q
  • u013368721
  • u013368721
  • 2014-08-14 19:29
  • 591

HDU 3487 Play with Chain(Splay)

题意:给出n个数,有两种操作,一种是将区间[a,b]取下,然后加入到取下后形成的数列的第c个位置之后,另一种是翻转区间[a,b]。 思路:用Splay能很好的完成两种操作。翻转用个懒惰标记标记一下就...
  • qian99
  • qian99
  • 2014-02-17 12:56
  • 426

HDU - 3487 Play with Chain __ Splay

题意:对1~n这n个数,进行m次操作,分别可以进行区间移动和区间反转,求最终的序列。 Splay Splay的基础题,按照要求进行区间移动和区间反转即可。 复杂度 O(m*logn)
  • ProLightsfxjh
  • ProLightsfxjh
  • 2017-03-17 23:24
  • 354

HDU 3487 Play with Chain (Splay tree)

转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove 再撸一发Spl...
  • ACM_cxlove
  • ACM_cxlove
  • 2012-07-30 10:35
  • 4003

hdu 3487 Play with Chain (Splay树) 区间切割 插入 翻转

hdu 3487 Play with Chain (Splay树) 区间切割 插入 翻转 关键注意:down 和 up find,kth,next,pre, RTO等当有flip时,都要d...
  • guognib
  • guognib
  • 2013-12-01 19:43
  • 851

HDU 3487 Play with Chain [平衡树splay]

HDU 3487 Play with Chain [平衡树splay]
  • ACTerminate
  • ACTerminate
  • 2017-07-20 10:38
  • 144

HDU3487 Play with Chain (Splay)

题意:给两种操作,一种是切下[a,b]这一段加到c这个位置之后,还有一个翻转[a,b]这个位置,操作过后输出序列。 Splay。。。。虽然理论比较简单,但本渣还是写了一下午+调了3个小时。。。 对...
  • eeeaaaaa
  • eeeaaaaa
  • 2014-12-12 20:35
  • 222
    个人资料
    • 访问:377168次
    • 积分:15879
    • 等级:
    • 排名:第782名
    • 原创:1254篇
    • 转载:13篇
    • 译文:0篇
    • 评论:61条
    文章分类