题目意思:
给定一个1,2,3,4...n的序列
操作1:
把第L到R个元素切掉,然后插入新的序列第k个元素后面
操作2:
第L个,到第R个元素之间的所有元素进行倒序。
splay模板:
这里我自己做了自己的splay模板,太慢!勉强能用!
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
const int maxint=~0U>>1;
/*
splay,各个节点之间需要传递的信息
*/
struct mark
{
bool reverse; //这个节点的所有子节点是否要颠倒
/*
bool b;
bool a;
表示a,b表示一些需要传递的参数,比如是否要倒置之类,或者区间加上一直值,减去一个值
*/
mark()
{
reverse=0;
}
//1要颠倒 0不要颠倒
};
vector<int>outputnum;
/*
splay的节点信息
*/
struct node
{
int key;
int size;
mark cd;
node *c[2];
node():key(0),size(0){c[0]=c[1]=this;}
node(int key_,node* c0_,node* c1_):
key(key_){c[0]=c0_;c[1]=c1_;}
node* rz(){return size=c[0]->size+c[1]->size+1,this;}
} Tnull,*null=&Tnull;
struct splay
{
node *root;
splay() /*初始化 不需要做任何修改*/
{
root=(new node(*null))->rz();
root->key=maxint;
}
/*把k节点的信息,传递到k节点的两个儿子,同时,如果是逆转操作,左右儿子
* 需要进行交换位置。 【只传递给两个儿子!】
* do_reversal有自动判断,当前node是否有信息要传递的功能
*/
void do_reversal(node* k)
{
if (k -> cd.reverse)//如果这个节点需要传递
{
k -> cd.reverse = 0; //标记为已经传递,标记下传,并且交换
swap(k -> c[0], k -> c[1]);//左右儿子交换
if (k -> c[0] != null) k -> c[0] -> cd.reverse ^= 1;
if (k -> c[1] != null) k -> c[1] -> cd.reverse ^= 1;
}
}
/*
* 从根节点把信息,向下传递2层
*/
void check()
{
do_reversal(root);//根的左右儿子逆转,先把根的信息处理完,do_reversal会自动判断当前节点是否要做操作
//然后判断,根的左右儿子是否有信息要传递
if (root -> c[0] != null) do_reversal(root -> c[0]);
if (root -> c[1] != null) do_reversal(root -> c[1]);
}
//zig,zigzig,finish,select操作,全部和key无关,不需要做任何修改
void zig(bool d)
{
node *t=root->c[d];
root->c[d]=null->c[d];
null->c[d]=root;
root=t;
}
void zigzig(bool d)
{
node *t=root->c[d]->c[d];
root->c[d]->c[d]=null->c[d];
null->c[d]=root->c[d];
root->c[d]=null->c[d]->c[!d];
null->c[d]->c[!d]=root->rz();
root=t;
}
void finish(bool d)
{
node *t=null->c[d],*p=root->c[!d];
while(t!=null)
{
t=null->c[d]->c[d];
null->c[d]->c[d]=p;
p=null->c[d]->rz();
null->c[d]=t;
}
root->c[!d]=p;
}
void select(int k) //第k+1个元素旋转到根,也就是有k个数字比要找的数字小
{
int t;
while(1)
{
check();
bool d=k>(t=root->c[0]->size);
if(k==t||root->c[d]==null)break;
if(d)k-=t+1;
bool dd=k>(t=root->c[d]->c[0]->size);
if(k==t||root->c[d]->c[dd]==null){zig(d);break;}
if(dd)k-=t+1;
d!=dd?zig(d),zig(dd):zigzig(d);
}
finish(0),finish(1);
root->rz();//更新根节点的size
}
/*
pg(node k);
打印整棵树,包括左右儿子信息,size,传递的参数
通常直接调用 pg(*root) 即可
*/
void pg(node k)//打印这棵树
{
cout<<k.key<<" [left son:";
if (k.c[0] != null) cout<<k.c[0] -> key;
else cout<<"none";
cout<<"] [right son:";
if (k.c[1] != null) cout<< k.c[1] -> key;
else cout<<"none";
cout<<"] [size =";
cout<<k.size<<"]" <<"逆转否?"<<" "<<k.cd.reverse<<"\n";
if (k.c[0] != null) pg(*k.c[0]);
if (k.c[1] != null) pg(*k.c[1]);
}
/*
* 输出这棵树的中序遍历,包括-maxint,和+maxin
* 调用方式通常直接为zhongxu(root)
*/
void zhongxu(node* k)
{
do_reversal(k);//根的左右儿子逆转
if (k -> c[0] != null) do_reversal(k -> c[0]);
if (k -> c[1] != null) do_reversal(k -> c[1]);
if (k -> c[0] != null) zhongxu(k -> c[0]);
cout<<k -> key<<" ";
if (k -> c[1] != null) zhongxu(k -> c[1]);
}
// vector<int>outputnum;必须定义
// 必须在调用整个函数之前初始化outputnum
void get_output_info(node* k)
{
do_reversal(k);//根的左右儿子逆转
if (k -> c[0] != null) do_reversal(k -> c[0]);
if (k -> c[1] != null) do_reversal(k -> c[1]);
if (k -> c[0] != null) get_output_info(k -> c[0]);
outputnum.push_back(k -> key);
if (k -> c[1] != null) get_output_info(k -> c[1]);
}
void output()
{
outputnum.clear();
get_output_info(root);
for (int i = 1; i != outputnum.size() - 2; ++ i) printf("%d ", outputnum[i]);
printf("%d\n", outputnum[outputnum.size() - 2]);
}
///
node* init(int x[], int n)//形成一颗初始树, 有n个元素,下标从1开始的数组
{
//因为是初始化,所以先添加了一个最小的节点-maxint进这棵树
root -> c[0] = (new node(-maxint, null, null)) -> rz();//左儿子插入一个新元素
root -> rz();
for (int i = 1; i <= n; ++ i)
{
transformation(i, i + 1);
root -> c[1] -> c[0] = (new node(x[i], null, null)) -> rz();
root -> c[1] -> rz();
root -> rz();
}
return root;
}
node* init_no_maxint(int x[], int n)//同上,但是不添加-maxint,和max进这棵树,这是为了方便合并
{
root -> c[0] = (new node(x[1], null, null)) -> rz();//左儿子插入一个新元素
root -> rz();
for (int i = 2; i <= n; ++ i)
{
transformation(i - 1, i);
root -> c[1] -> c[0] = (new node(x[i], null, null)) -> rz();
root -> c[1] -> rz();
root -> rz();
}
transformation(n, n + 1);
delete root -> c[1];
root -> c[1] = null;
return root -> rz();
}
/*
* clear()以下为删除把整个splay清空为初始化状态
*/
void dfs_clear(node *k)
{
if (k -> c[0] != null)
{
dfs_clear(k -> c[0]);
delete (k -> c[0]);
}
if (k -> c[1] != null)
{
dfs_clear(k -> c[1]);
delete k -> c[1];
}
}
node* clear() //删除整棵树,只留下一个maxint在树中
{
int allsize = root -> size;
select(allsize - 1);
dfs_clear(root);
root -> c[0] = root -> c[1] = null;
return root;
}
/*
* 把第left个节点旋转到根,right为根的右儿子
* 也就是提取区间[left+1,right-1]
* 当然,这里包括-maxint, maxint这2个节点
*/
node* transformation(int left, int right)
{
select(left - 1);
node *oldroot = root;
root = root -> c[1];
select(right -left - 1);
node *t = root;
root = oldroot;
root -> c[1] = t;
return root -> rz();
}
/*
* 把[left+1, right -1]之间的东西倒置
*/
node* reversal(int left, int right) // (left,right)之间要倒置,不包含left,right
{
transformation(left, right);
root -> c[1] -> c[0] -> cd.reverse ^= 1;
return root;
}
int sel(int k){return select(k-1),root->key;} //第k名的是谁
} sp;
struct interval// 形成区间的一个splay
{
splay core;//包含头一个-max,后一个max
inline int size()
{
return core.root -> size - 2;
}
inline void output()
{
core.output();
}
inline void clear()
{
core.clear();
}
inline void init(int x[], int n)//初始化,给core里初始值
//下标从1开始,一共n个元素!
{
core.init(x, n);
}
/*
* 第left个元素,到第right个元素,全部倒转
*/
void daozhuan(int left, int right)
{
right += 2;
core.reversal(left, right);
}
/*
* 按照顺序输出所有元素,注意,这里会让所有传递信息进行传递!
*/
void output_all_element()
{
core.zhongxu(core.root);
cout<<endl;
}
node* delete_qujian(int left, int right)
{
right += 2;
core.transformation(left, right);
node *ret = core.root -> c[1] -> c[0];
core.root -> c[1] -> c[0] = null;
core.root -> c[1] -> rz();
core.root -> rz();
return ret;
}
void insert_node(node *newinter, int k)//在区间[1,k],[k+1,n]之间插入
{
++k; //因为存在-max的元素,所以区间都要后置一点
core.transformation(k, k + 1);
core.root -> c[1] -> c[0] = newinter;
}
/*
* 在第k个元素后面插入n个元素,n个元素保存在x[1..n]中。 下标为1开始
*/
void insert(int x[], int n, int k)
{
splay tmp;
node *tmproot = tmp.init_no_maxint(x, n);
insert_node(tmproot, k);
}
}qujian;
int a[300000 + 100];
int main()
{
int data, que;
char s[100];
while (1)
{
scanf("%d%d", &data, &que);
if (data == -1 && que == -1) break;
qujian.clear();
for (int i = 1; i <= data; ++ i) a[i] = i;
qujian.init(a, data);
while (que--)
{
scanf("%s", s);
if (s[0] == 'C')
{
// cout<<"!"<<endl;
int left, right, k;
scanf("%d%d%d", &left, &right, &k);
node *tmp = qujian.delete_qujian(left, right);
qujian.insert_node(tmp, k);
}else{
int left, right;
scanf("%d%d", &left, &right);
qujian.daozhuan(left, right);
}
}
qujian.output();
}
return 0;
}