hdu 3487 Play with Chain(splay tree)

Play with Chain

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


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
 

Source
2010 ACM-ICPC Multi-University Training Contest(5)——Host by BJTU
 

Recommend
zhengfeng
功能:区间剪切,区间插入,区间翻转。。。

CUT   l r c:把第l-1节点splay到root节点,把第r+1节点splay到 ch[root][1]  节点,ch[ch[root][1]][0]为根的子树就是要剪切掉的部分

插入时:把第 c 节点splay到root节点,把第c的后继结点节点splay到 ch[root][1]  节点,此时ch[ch[root][1]][0]为根的子树就为空树,此时就可以把剪切掉的那部分插入到ch[ch[root][1]][0]为根的子树上;

FLIP  l r:翻转操作要用到延迟标记rev(类似于线段树),push_up,push_down,把第l-1节点splay到root节点,把第r+1节点splay到 ch[root][1]  节点,ch[ch[root][1]][0]为根的子树就是要翻转的部分(同剪切);

输出是利用中根遍历;

我的代码:(留着以后当模版用,O(∩_∩)O哈哈~)

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<algorithm>
#define N 500001
#define Key_value ch[ch[root][1]][0]
using namespace std;
int n,q;
int key[N];
int size[N],pre[N],rev[N];
int ch[N][2],tot,root,data[N];
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;
	size[r]=1;
}
void push_up(int r){
	size[r]=size[ch[r][0]]+size[ch[r][1]]+1;
}
void push_down(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;
	}
}
int flag;
void Inorder(int r)
{
    if(r==0)
    return;
    push_down(r);
    Inorder(ch[r][0]);
    if(key[r]!=-1)
    {
        if(flag)
        {
            printf("%d",key[r]);flag=0;
        }
        else
        printf(" %d",key[r]);
    }
    Inorder(ch[r][1]);
}
void Rotate(int x,int kind){
	int y=pre[x];
	push_down(y);
	push_down(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;
	push_up(y);
}
void Splay(int r,int goal){
	push_down(r);
	while(pre[r]!=goal){
		if(pre[pre[r]]==goal)
			Rotate(r,ch[pre[r]][0]==r);
		else{
			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);
			}
		}
	}
	push_up(r);
	if(goal==0) root=r;
}
void RotateTo(int k,int goal) {
    int r=root;
    push_down(r);
    while(size[ch[r][0]]!=k){
        if(k<size[ch[r][0]]){
            r=ch[r][0];
        } else {
            k-=(size[ch[r][0]]+1);
            r=ch[r][1];
        }
        push_down(r);
    }
    Splay(r,goal);
}
int Get_Kth(int r,int k){
	push_down(r);
	int t=size[ch[r][0]]+1;
	if(t==k)
		return r;
	if(t>k)
		return Get_Kth(ch[r][0],k);
	else
		return Get_Kth(ch[r][1],k-t);
}
int Get_Min(int r){
	push_down(r);
	while(ch[r][0]){
		r=ch[r][0];
		push_down(r);
	}
	return r;
}
int Get_Max(int r){
	push_down(r);
	while(ch[r][1]){
		r=ch[r][1];
		push_down(r);
	}
	return r;
}
void Reversal(int l,int r){
	RotateTo(l-1,0);
	RotateTo(r+1,root);
	rev[Key_value]^=1;
}
void build(int &r,int L,int R,int fa)
{
    if(L>R)
    return;
    int mid=(L+R)/2;
    newnode(r,data[mid],fa);
    build(ch[r][0],L,mid-1,r);
    build(ch[r][1],mid+1,R,r);
    push_up(r);
}
void Init()
{
    tot=root=0;
    ch[0][0]=ch[0][1]=pre[0]=size[0]=0;
    newnode(root,-1,0);
    newnode(ch[root][1],-1,root);
    //size[root]=2;
    for(int i=1;i<=n;i++)
    data[i]=i;
    build(Key_value,1,n,ch[root][1]);
    push_up(ch[root][1]);
    push_up(root);
}
void ins(int c,int r)
{
    RotateTo(c,0);
  int x=Get_Min(ch[root][1]);
  Splay(x,root);
  Key_value=r;
  pre[Key_value]=ch[root][1];
}
int Delete(int l,int r)
{
	RotateTo(l-1,0);
	RotateTo(r+1,root);
	int kk;
	kk=Key_value;
	pre[Key_value]=0;
	Key_value=0;
	push_up(ch[root][1]);
	push_up(root);
	return kk;
}
char str[10];
int main(){
	//freopen("editor1.in","r",stdin);
	while(scanf("%d%d",&n,&q)!=EOF){
	    if(n==-1&&q==-1)
	    break;
		Init();
		int k,l,r,c;
		while(q--){
			scanf("%s",str);
			if(str[0]=='C'){
				scanf("%d%d%d",&l,&r,&c);
				getchar();
				k=Delete(l,r);
				ins(c,k);
			}
			else if(str[0]=='F'){
				scanf("%d%d",&l,&r);
				getchar();
				Reversal(l,r);
			}
		}
		flag=1;
       Inorder(root);
       printf("\n");
    }
	return 0;
}


你可能感兴趣的:(tree,delete,insert,Build,UP,Numbers)