splay<完结篇>

继线段树后掌握的又一大解决区间问题的神器(更是完美掩盖了线段树的缺点 除了写出来的常数有点大.....真的遇到卡常题还是早点GG吧

首先 splay的核心是伸展操作(并没有AVL和红黑树那样保持严格的左右平衡 但是相对treap而言还是比较平衡的 然后注意的是遇到删除的操作 注意写内存池 (不然就是TLE或者MLE 一般数组实现内存池吧  详情可参考kuangbin大神的splay模板

贴上我伸展部分的代码(这个只是对于没有打标记的....如果带有更新标记那就和线段树的lazy标记一样搞搞就行 记得转的时候先传哪个再传哪个即可

void rotate(int x,int kind){
    int y=pre[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;
    up(y);up(x);    
}
void splay(int x,int goal){
    while(pre[x]!=goal){
        if(pre[pre[x]]==goal){
            rotate(x,ch[pre[x]][0]==x);
        }
        else{
            int y=pre[x];
            int kind=ch[pre[y]][0]==y;
            if(ch[y][kind]==x){
                rotate(x,!kind);
                rotate(x,kind);
            }
            else{
                rotate(y,kind);
                rotate(x,kind);
            }
        }
    }
    if(goal==0) root=x;
    up(x);
}

其他的部分就是因题目而言了

题海战术:

1.poj  3468(线段树裸题 用来练习伸展树  常数有点大 

A Simple Problem with Integers
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 124890   Accepted: 38711
Case Time Limit: 2000MS

Description

You have N integers, A1A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of AaAa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15
#include <algorithm>
#include <iostream>
#include <cstdio>
#define N 100005
#define ll long long
#define rl child[child[root][1]][0]
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}
int child[N][2],size[N],pre[N],a[N],ke[N];
ll sum[N];
int flag[N];
int n,q,root,cnt;
void newnode(int &x,int fa,int key){
    cnt++;x=cnt;
    sum[x]=flag[x]=0;pre[x]=fa;size[x]=1;ke[x]=key;
    child[x][1]=child[x][0]=0;
}
void up(int x){
    size[x]=size[child[x][0]]+size[child[x][1]]+1;
    sum[x]=sum[child[x][0]]+sum[child[x][1]]+ke[x];
}
void down(int x){
    if(flag[x]!=0){
        if(child[x][0]){
            ke[child[x][0]]+=flag[x];sum[child[x][0]]+=(ll)size[child[x][0]]*flag[x];
            flag[child[x][0]]+=flag[x];
        }
        if(child[x][1]){
            ke[child[x][1]]+=flag[x];sum[child[x][1]]+=(ll)size[child[x][1]]*flag[x];
            flag[child[x][1]]+=flag[x];
        }
        flag[x]=0;
    }
}
void built(int &x,int l,int r,int fa){
    if(l>r) return ;
    int mid=(l+r)>>1;
    newnode(x,fa,a[mid]);
    built(child[x][0],l,mid-1,x);
    built(child[x][1],mid+1,r,x);
    up(x);
}
void add(int x,int vul){
    ke[x]+=vul;sum[x]+=(ll)size[x]*vul;
    flag[x]+=vul;
}
void rotate(int x,int kind){
    int y=pre[x];
    down(y);down(x);
    child[y][!kind]=child[x][kind];
    pre[child[x][kind]]=y;
    up(y);
    if(pre[y]) child[pre[y]][child[pre[y]][1]==y]=x;
    pre[x]=pre[y];
    child[x][kind]=y;pre[y]=x;
    up(x);
}
void splay(int x,int goal){
    down(x);
    while(pre[x]!=goal){
        if(pre[pre[x]]==goal){
            int kind=child[pre[x]][0]==x;
            rotate(x,kind);
        }
        else{
            int y=pre[x];
            int kind=child[pre[y]][0]==y;
            if(child[y][kind]==x){
                rotate(x,!kind);
                rotate(x,kind);
            }
            else{
                rotate(y,kind);
                rotate(x,kind);
            }
        }
    }
    if(goal==0) root=x;
    up(x); 
}
int find1(int t,int x){
    down(x);
    if(t==size[child[x][0]]+1) return x;
    else if(t<size[child[x][0]]+1) return find1(t,child[x][0]);
    else return find1(t-1-size[child[x][0]],child[x][1]);
    up(x); 
}
void update(int l,int r,int vul){
    splay(find1(l,root),0);
    splay(find1(r+2,root),root);
    add(rl,vul);
    up(child[root][1]);up(root);
}
ll Sum(int l,int r){
    splay(find1(l,root),0);
    splay(find1(r+2,root),root);
    return sum[rl];
}
void init(){
    for(int i=1;i<=n;i++) a[i]=read();
    root=cnt=0;
    size[0]=ke[0]=sum[0]=0;
    newnode(root,0,-1);
    newnode(child[root][1],root,-1);
    built(rl,1,n,child[root][1]);
    up(child[root][1]);
    up(root);
}
int main(){
    while(scanf("%d %d",&n,&q)!=EOF){
        init();char str[20];int t1,t2,t3;
        while(q--){
            scanf(" %s",str);t1=read();t2=read();
            if(str[0]=='C'){
                t3=read();
                update(t1,t2,t3);
            }
            else{
                printf("%lld\n",Sum(t1,t2));
            }
        }
    }
    return 0;
}

2.bzoj 1588(我记得1A是用的treap 很明显的找前驱和后继与这个值的绝对值最小值之和

1588: [HNOI2002]营业额统计

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 18106  Solved: 7497
[Submit][Status][Discuss]

Description

营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。  输入输出要求

Input

第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i
天公司的营业额。
天数n<=32767,
每天的营业额ai <= 1,000,000。
最后结果T<=2^31

 

Output

输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。

Sample Input

6
5
1
2
5
4
6

Sample Output

12
/**************************************************************
    Problem: 1588
    User: wang9897
    Language: C++
    Result: Accepted
    Time:252 ms
    Memory:3132 kb
****************************************************************/
 
#include <bits/stdc++.h>
#define N 40005
#define ll long long
#define INF 0x3f3f3f3f
#define rl ch[ch[root][1]][0]
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}
int size[N],pre[N],ch[N][2],key[N];
int root,cnt,n;
map<int,int>ma;
void newnode(int &x,int vul,int fa){
    cnt++;x=cnt;
    size[x]=1;key[x]=vul;pre[x]=fa;
    ch[x][0]=ch[x][1]=0;
}
void rotate(int x,int kind){
    int y=pre[x];
    ch[y][!kind]=ch[x][kind];
    pre[ch[x][kind]]=y;pre[x]=pre[y];
    if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
    ch[x][kind]=y;pre[y]=x;
}
void splay(int x,int goal){
    while(pre[x]!=goal){
        if(pre[pre[x]]==goal){
            int kind=ch[pre[x]][0]==x;
            rotate(x,kind);
        }
        else{
            int y=pre[x];
            int kind=ch[pre[y]][0]==y;
            if(ch[y][kind]==x){
                rotate(x,!kind);
                rotate(x,kind);
            }
            else{
                rotate(y,kind);
                rotate(x,kind);
            }
        }
    }
    if(goal==0) root=x;
}
int inset(int &x,int vul,int fa){
    if(x==0){
        newnode(x,vul,fa);
        return x;
    }
    else if(key[x]<vul) inset(ch[x][1],vul,x);
    else inset(ch[x][0],vul,x);
}
int min_max;
void Min_max(int x){
    if(x==0) return ;
    min_max=key[x];
    Min_max(ch[x][1]);
}
int max_min;
void Max_min(int x){
    if(x==0) return ;
    max_min=key[x];
    Max_min(ch[x][0]);
}
int ab(int x,int y){
    int t=x-y;
    if(t<0) return -1*t;
    else return t;
}
int main(){
    ios::sync_with_stdio(false);
    n=read();pre[0]=0;
    root=cnt=0;
    ll sum=0;int t;
    for(int i=1;i<=n;i++){
        t=read();
        if(ma[t]==1) continue;
        ma[t]=1;
        splay(inset(root,t,0),0);
        if(i==1){
            sum+=t;continue;
        }
        min_max=INF;max_min=-INF;
        Min_max(ch[root][0]);Max_min(ch[root][1]);
        sum+=min(ab(t,min_max),ab(t,max_min));
    }
    printf("%lld\n",sum);
    return 0;
}

3.HDU 1890

Robotic Sort

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4819    Accepted Submission(s): 2163


Problem Description
Somewhere deep in the Czech Technical University buildings, there are laboratories for examining mechanical and electrical properties of various materials. In one of yesterday’s presentations, you have seen how was one of the laboratories changed into a new multimedia lab. But there are still others, serving to their original purposes. 

In this task, you are to write software for a robot that handles samples in such a laboratory. Imagine there are material samples lined up on a running belt. The samples have different heights, which may cause troubles to the next processing unit. To eliminate such troubles, we need to sort the samples by their height into the ascending order. 

Reordering is done by a mechanical robot arm, which is able to pick up any number of consecutive samples and turn them round, such that their mutual order is reversed. In other words, one robot operation can reverse the order of samples on positions between A and B. 

A possible way to sort the samples is to find the position of the smallest one (P1) and reverse the order between positions 1 and P1, which causes the smallest sample to become first. Then we find the second one on position P and reverse the order between 2 and P2. Then the third sample is located etc. 



The picture shows a simple example of 6 samples. The smallest one is on the 4th position, therefore, the robot arm reverses the first 4 samples. The second smallest sample is the last one, so the next robot operation will reverse the order of five samples on positions 2–6. The third step will be to reverse the samples 3–4, etc. 

Your task is to find the correct sequence of reversal operations that will sort the samples using the above algorithm. If there are more samples with the same height, their mutual order must be preserved: the one that was given first in the initial order must be placed before the others in the final order too.
 

 

Input
The input consists of several scenarios. Each scenario is described by two lines. The first line contains one integer number N , the number of samples, 1 ≤ N ≤ 100 000. The second line lists exactly N space-separated positive integers, they specify the heights of individual samples and their initial order. 

The last scenario is followed by a line containing zero.
 

 

Output
For each scenario, output one line with exactly N integers P1 , P1 , . . . PN ,separated by a space.
Each Pi must be an integer (1 ≤ Pi ≤ N ) giving the position of the i-th sample just before the i-th reversal operation. 

Note that if a sample is already on its correct position Pi , you should output the number Pi anyway, indicating that the “interval between Pi and Pi ” (a single sample) should be reversed. 
 

 

Sample Input
6 3 4 5 1 6 2 4 3 3 2 1 0
 

 

Sample Output
4 6 4 5 6 6 4 2 4 4
#include <bits/stdc++.h>
using namespace std;
#define N 100005
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}
int root,cnt,n;
int size[N],pre[N],ch[N][2],flag[N];
void newnode(int &x,int fa,int vul){
    x=vul;
    size[x]=1;pre[x]=fa;
    ch[x][0]=ch[x][1]=flag[x]=0;
}
void update(int x){
    if(!x) return ;
    flag[x]^=1;
    swap(ch[x][0],ch[x][1]);
}
void down(int x){
    if(flag[x]){
        if(ch[x][0]) update(ch[x][0]);
        if(ch[x][1]) update(ch[x][1]);    
        flag[x]^=1;
    }
}
void up(int x){
    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void rotate(int x,int kind){
    int y=pre[x];
    down(y);down(x);
    ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y;
    up(y);
    if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
    pre[x]=pre[y];pre[y]=x;ch[x][kind]=y;
    up(x);
}
void splay(int x,int goal){
    down(x);
    while(pre[x]!=goal){
        if(pre[pre[x]]==goal){
            down(pre[x]);down(x);
            int kind=ch[pre[x]][0]==x;
            rotate(x,kind);
        }
        else{
            int y=pre[x];
            down(pre[y]);down(y);down(x);
            int kind=ch[pre[y]][0]==y;
            if(ch[y][kind]==x){
                rotate(x,!kind);rotate(x,kind);
            }
            else{
                rotate(y,kind);rotate(x,kind);
            }
        }
    }
    if(goal==0) root=x;
    up(x); 
}
void built(int &x,int l,int r,int fa){
    if(l>r) return ;
    int mid=(l+r)>>1;
    newnode(x,fa,mid);
    built(ch[x][0],l,mid-1,x);
    built(ch[x][1],mid+1,r,x);
    up(x);
}
int Min_max(int x){
    down(x);
    while(ch[x][1]!=0){
        x=ch[x][1];down(x);
    }
    return x;
}
void remove(int x){
    down(x);
    if(ch[x][0]==0){
        pre[ch[x][1]]=0;
        root=ch[x][1];
    }
    else{
        splay(Min_max(ch[x][0]),root);
        ch[ch[x][0]][1]=ch[x][1];
        pre[ch[x][1]]=ch[x][0];
        root=ch[x][0];pre[ch[x][0]]=0;
    }
    up(root);
}
typedef struct node{
    int id,vul;
    friend bool operator <(node aa,node bb){
        if(aa.vul==bb.vul) return aa.id<bb.id;
        return aa.vul<bb.vul;
    }
}node;
node d[N];
int main(){
    ios::sync_with_stdio(false);
    while(n=read()){
        if(n==0) break;
        for(int i=1;i<=n;i++){
            d[i].vul=read();
            d[i].id=i;
        }
        sort(d+1,d+n+1);
        root=cnt=0;
        built(root,1,n,0);
        for(int i=1;i<n;i++){
            splay(d[i].id,0);
            printf("%d ",i+size[ch[root][0]]);
            update(ch[root][0]);
            remove(root);
        }
        printf("%d\n",n);
    }
    return 0;
}

4.POJ 3580

SuperMemo
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 17452   Accepted: 5479
Case Time Limit: 2000MS

Description

Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to play a memorizing game. At first, the host tells the participant a sequence of numbers, {A1A2, ... An}. Then the host performs a series of operations and queries on the sequence which consists:

  1. ADD x y D: Add D to each number in sub-sequence {Ax ... Ay}. For example, performing "ADD 2 4 1" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5, 5}
  2. REVERSE x y: reverse the sub-sequence {Ax ... Ay}. For example, performing "REVERSE 2 4" on {1, 2, 3, 4, 5} results in {1, 4, 3, 2, 5}
  3. REVOLVE x y T: rotate sub-sequence {Ax ... AyT times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
  4. INSERT x P: insert P after Ax. For example, performing "INSERT 2 4" on {1, 2, 3, 4, 5} results in {1, 2, 4, 3, 4, 5}
  5. DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
  6. MIN x y: query the participant what is the minimum number in sub-sequence {Ax ... Ay}. For example, the correct answer to "MIN 2 4" on {1, 2, 3, 4, 5} is 2

To make the show more interesting, the participant is granted a chance to turn to someone else that means when Jackson feels difficult in answering a query he may call you for help. You task is to watch the TV show and write a program giving the correct answer to each query in order to assist Jackson whenever he calls.

Input

The first line contains (≤ 100000).

The following n lines describe the sequence.

Then follows M (≤ 100000), the numbers of operations and queries.

The following M lines describe the operations and queries.

Output

For each "MIN" query, output the correct answer.

Sample Input

5
1 
2 
3 
4 
5
2
ADD 2 4 1
MIN 4 5

Sample Output

5
#include <iostream>
#include <algorithm>
#include <cstdio>
#define N 100005
#define rl ch[ch[root][1]][0]
#define lr ch[ch[root][0]][1]
#define INF 0x3f3f3f3f
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}
int size[N],pre[N],add[N],flag[N],Min[N],ch[N][2],key[N];
int a[N],s[N];
int root,cnt1,cnt2,n;
void newnode(int &x,int fa,int vul){
    if(cnt2) x=s[cnt2--];
    else x=(++cnt1);
    size[x]=1;pre[x]=fa;Min[x]=key[x]=vul;
    ch[x][0]=ch[x][1]=add[x]=flag[x]=0;
}
void reverse(int x){
    if(!x) return ;
    swap(ch[x][0],ch[x][1]);
    flag[x]^=1;
}
void push(int x){
    if(add[x]){
        if(ch[x][0]) {
        add[ch[x][0]]+=add[x];Min[ch[x][0]]+=add[x];key[ch[x][0]]+=add[x];}
        if(ch[x][1]) {
        add[ch[x][1]]+=add[x];Min[ch[x][1]]+=add[x];key[ch[x][1]]+=add[x];}
        add[x]=0;
    }
    if(flag[x]){
        if(ch[x][0]) reverse(ch[x][0]);
        if(ch[x][1]) reverse(ch[x][1]);
        flag[x]=0;
    }
}
void up(int x){
    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
    Min[x]=min(key[x],min(Min[ch[x][0]],Min[ch[x][1]]));
}
void rotate(int x,int kind){
    int y=pre[x];
    push(y);push(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];pre[y]=x;ch[x][kind]=y;
    up(y);up(x);
}
void splay(int x,int goal){
    push(x);
    while(pre[x]!=goal){
        if(pre[pre[x]]==goal){
            push(pre[x]);push(x);
            int kind=ch[pre[x]][0]==x;
            rotate(x,kind);
        }
        else{
            int y=pre[x];
            push(pre[y]);push(y);push(x);
            int kind=ch[pre[y]][0]==y;
            if(ch[y][kind]==x){
                rotate(x,!kind);rotate(x,kind);
            }
            else{
                rotate(y,kind);
                rotate(x,kind);
            }
        }
    }
    if(goal==0) root=x;
    up(x);
}
int find1(int x,int t){
    push(x);
    if(t==size[ch[x][0]]+1) return x;
    else if(t<size[ch[x][0]]+1) return find1(ch[x][0],t);
    else return find1(ch[x][1],t-size[ch[x][0]]-1);
    up(x);
}
void Add(int l,int r,int vul){
    splay(find1(root,l),0);splay(find1(root,r+2),root);
    add[rl]+=vul;Min[rl]+=vul;key[rl]+=vul;
    up(ch[root][1]);up(root);
}
void update(int l,int r){
    splay(find1(root,l),0);splay(find1(root,r+2),root);
    reverse(rl);
    up(ch[root][1]);up(root);
}
void revolve(int l,int r,int t){
    int len=t%(r-l+1);
    if(!len) return ;
    splay(find1(root,r-len+1),0);
    splay(find1(root,r+2),root);
    up(ch[root][1]);up(root);
    int tmp=rl;
    rl=0;
    splay(find1(root,l),0);
    splay(find1(root,l+1),root);
    pre[tmp]=ch[root][1];
    rl=tmp;
    up(ch[root][1]);
    up(root);
}
void insert(int t,int p){
    splay(find1(root,t+1),0);
    splay(find1(root,t+2),root);
    newnode(rl,ch[root][1],p);
    up(ch[root][1]);up(root);
}
void delet(int t){
    splay(find1(root,t),0);
    splay(find1(root,t+2),root);
    s[++cnt2]=rl;
    pre[rl]=0;
    rl=0;
    up(ch[root][1]);up(root);
}
int min1(int l,int r){
    splay(find1(root,l),0);
    splay(find1(root,r+2),root);
    return Min[rl];
}
void built(int &x,int l,int r,int fa){
    if(l>r) return ;
    int mid=(l+r)>>1;
    newnode(x,fa,a[mid]);
    built(ch[x][0],l,mid-1,x);
    built(ch[x][1],mid+1,r,x);    
    up(x);
}
void init(){
    for(int i=1;i<=n;i++) a[i]=read();
    root=cnt1=cnt2=0;
    size[root]=pre[root]=add[root]=flag[root]=ch[root][0]=ch[root][1]=0;
    Min[root]=INF;
    newnode(root,0,INF);
    newnode(ch[root][1],root,INF);
    built(rl,1,n,ch[root][1]);
    up(ch[root][1]);up(root);
}
int main(){
    ios::sync_with_stdio(false);
    while(scanf("%d",&n)!=EOF){
        init();
        int q=read();char str[102];
        int t1,t2,t3;
        while(q--){
            scanf(" %s",str);
            if(str[0]=='A'){
                t1=read();t2=read();t3=read();
                Add(t1,t2,t3);
            } 
            else if(str[0]=='R'&&str[3]=='E'){
                t1=read();t2=read();
                update(t1,t2);
            }
            else if(str[0]=='R'){
                t1=read();t2=read();t3=read();
                revolve(t1,t2,t3);
            }
            else if(str[0]=='I'){
                t1=read();t2=read();
                insert(t1,t2);
            }
            else if(str[0]=='D'){
                t1=read();
                delet(t1);
            }
            else if(str[0]=='M'){
                t1=read();t2=read();
                printf("%d\n",min1(t1,t2));
            }
        }
    }
    return 0;
}

5.HDU 3487

Play with Chain

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


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
#include <bits/stdc++.h>
#define N 300005
#define rl ch[ch[root][1]][0]
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}
int pre[N],size[N],ch[N][2],key[N],flag[N];
int root,cnt;
int n,q;
void newnode(int &x,int fa,int vul){
    cnt++;x=cnt;
    pre[x]=fa;size[x]=1;key[x]=vul;
    ch[x][0]=ch[x][1]=flag[x]=0;
}
void update_re(int x){
    if(!x) return ;
    swap(ch[x][0],ch[x][1]);
    flag[x]^=1;
}
void push(int x){
    if(flag[x]){
        update_re(ch[x][0]);
        update_re(ch[x][1]);
        flag[x]=0;
    }
}
void up(int x){
    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void rotate(int x,int kind){
    int y=pre[x];
    push(y);push(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];pre[y]=x;ch[x][kind]=y;
    up(y);up(x);
}
void splay(int x,int goal){
    push(x);
    while(pre[x]!=goal){
        if(pre[pre[x]]==goal){
            push(pre[x]);push(x);
            int kind=ch[pre[x]][0]==x;
            rotate(x,kind);
        }
        else{
            int y=pre[x];
            push(pre[y]);push(y);push(x);
            int kind=ch[pre[y]][0]==y;
            if(ch[y][kind]==x){
                rotate(x,!kind);rotate(x,kind);
            }
            else{
                rotate(y,kind);rotate(x,kind);
            }
        }
    }
    if(goal==0) root=x;
    up(x);
}
int find1(int x,int t){
    push(x);
    if(t==size[ch[x][0]]+1) return x;
    else if(t<size[ch[x][0]]+1) return find1(ch[x][0],t);
    else return find1(ch[x][1],t-size[ch[x][0]]-1);
    up(x);
}
void Cut(int l,int r,int z){
    splay(find1(root,l),0);
    splay(find1(root,r+2),root);
    int temp=rl;
    rl=0;
    up(ch[root][1]);up(root);
    splay(find1(root,z+1),0);
    splay(find1(root,z+2),root);
    rl=temp;
    pre[temp]=ch[root][1];
    up(ch[root][1]);up(root);
}
void res(int l,int r){
    splay(find1(root,l),0);
    splay(find1(root,r+2),root);
    update_re(rl);
    up(ch[root][1]);up(root);
}
bool flag1;
void print_f(int x){
    if(!x) return ;
    push(x);
    print_f(ch[x][0]);
    if(key[x]!=-1){
        if(flag1==0) printf("%d",key[x]);
        else printf(" %d",key[x]);
        flag1=1;
    }
    print_f(ch[x][1]);
}
void built(int &x,int l,int r,int fa){
    if(l>r) return ;
    int mid=(l+r)>>1;
    newnode(x,fa,mid);
    built(ch[x][0],l,mid-1,x);
    built(ch[x][1],mid+1,r,x);
    up(x);
}
void init(){
    root=cnt=0;
    size[root]=ch[root][0]=ch[root][1]=pre[root]=flag[root]=0;
    newnode(root,0,-1);
    newnode(ch[root][1],root,-1);
    built(rl,1,n,ch[root][1]);
    up(ch[root][1]);up(root);
}
int main(){
    char str[20];
    int x,y,z;
    ios::sync_with_stdio(false);
    while(scanf("%d %d",&n,&q)==2){
        if(n==-1&&q==-1) break;
        init();
        while(q--){
            scanf(" %s",str);
            if(str[0]=='C'){
                scanf("%d %d %d",&x,&y,&z);
                Cut(x,y,z);    
            }
            else{
                scanf("%d %d",&x,&y);
                res(x,y);
            }
        }
        flag1=0;
        print_f(root);
        printf("\n");
    }
    return 0;
}
posted @ 2018-01-31 00:26  wang9897  阅读(373)  评论(1编辑  收藏  举报