#include<cstdio>
#include<cstring>
#include<algorithm>
#define keytree (ch[ ch[root][1] ][0])
using namespace std;
const int SIZEN = 210005;
struct SplayTree{
int ch[SIZEN][2];
int sz[SIZEN];
int pre[SIZEN];
int top,root;
int k1,k2,n,cnt;
inline void change(int x){
swap(ch[x][0],ch[x][1]);
}
inline void pushup(int x){
sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + 1;
}
inline void pushdown(int x){
if(lazy[x]){
if(ch[x][0]){
lazy[ ch[x][0] ] ^= 1;
change(ch[x][0]);
}
if(ch[x][1]){
lazy[ ch[x][1] ] ^= 1;
change(ch[x][1]);
}
lazy[x] = 0;
}
if(add[x]){
if(ch[x][0]){
add[ ch[x][0] ] += add[x];
val[ ch[x][0] ] += add[x];
}
if(ch[x][1]){
add[ ch[x][1] ] += add[x];
val[ ch[x][1] ] += add[x];
}
add[x] = 0;
}
}
inline void Rotate(int x,int f){
int y = pre[x];
pushdown(y);
pushdown(x);
ch[y][!f] = ch[x][f];
pre[ ch[x][f] ] = y;
pre[x] = pre[y];
if(pre[x]) ch[ pre[y] ][ ch[ pre[y] ][1] == y ] = x;
ch[x][f] = y;
pre[y] = x;
pushup(y);
}
inline void Splay(int x,int goal){
pushdown(x);
while(pre[x] != goal){
if(pre[ pre[x] ] == goal){
Rotate(x,ch[ pre[x] ][0] == x);
}
else{
int y = pre[x],z = pre[y];
int f = (ch[z][0] == y);
if(ch[y][f] == x){
Rotate(x,!f),Rotate(x,f);
}
else{
Rotate(y,f),Rotate(x,f);
}
}
}
pushup(x);
if(goal == 0) root = x;
}
inline void Rotateto(int k,int goal){
int x = root;
while(sz[ ch[x][0] ] != k){
if(sz[ ch[x][0] ] > k){
x = ch[x][0];
}
else{
k -= sz[ ch[x][0] ] + 1;
x = ch[x][1];
}
pushdown(x);
}
Splay(x,goal);
}
inline void debug(){
printf("root:%d\n",root);
Travel(root);
}
inline void Travel(int x){
pushdown(x);
if(ch[x][0]) Travel(ch[x][0]);
printf("node:%d lson:%d rson:%d pre:%d sz:%d val:%d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
if(ch[x][1]) Travel(ch[x][1]);
}
int Newnode(int c){
int x = ++top;
ch[x][0] = ch[x][1] = pre[x] = 0;
val[x] = c;
lazy[x] = add[x] = 0;
sz[x] = 1;
return x;
}
inline void build(int &x,int l,int r,int f){
if(l > r) return;
int mid = (l + r) >> 1;
x = Newnode(num[mid]);
build(ch[x][0],l,mid - 1,x);
build(ch[x][1],mid + 1,r,x);
pre[x] = f;
pushup(x);
}
inline void init(){
ch[0][0] = ch[0][1] = pre[0] = 0;
sz[0] = val[0] = 0;
lazy[0] = add[0] = 0;
top = root = 0;
cnt = n;
root = Newnode(1);
ch[root][1] = Newnode(1);
pre[ ch[root][1] ] = root;
sz[root] = 2;
for(int i = 1; i <= n;i ++) scanf("%d",&num[i]);
build(keytree,1,n,ch[root][1]);
pushup(ch[root][1]);
pushup(root);
}
inline int findmin(int x){
while(ch[x][0]){
pushdown(x);
x = ch[x][0];
}
return x;
}
inline int findmax(int x){
while(ch[x][1]){
pushdown(x);
x = ch[x][1];
}
return x;
}
inline int findhead(){
int k = 1,x = root;
while(sz[ ch[x][0] ] != k){
if(sz[ ch[x][0] ] > k){
x = ch[x][0];
}
else{
k -= sz[ ch[x][0] ] + 1;
x = ch[x][1];
}
pushdown(x);
}
return x;
}
inline int findtail(){
int k = cnt,x = root;
while(sz[ ch[x][0] ] != k){
if(sz[ ch[x][0] ] > k){
x = ch[x][0];
}
else{
k -=sz[ ch[x][0] ] + 1;
x = ch[x][1];
}
pushdown(x);
}
return x;
}
inline void Add(){
int c;
scanf("%d",&c);
Rotateto(0,0);
Rotateto(k2 + 1,root);
add[keytree] += c;
val[keytree] += c;
}
inline void Rev(){
Rotateto(0,0);
Rotateto(k1 + 1,root);
lazy[keytree] ^= 1;
change(keytree);
}
inline void Insert(){
int x = root,c;
scanf("%d",&c);
int head = findhead();
Rotateto(1,0);
Rotateto(2,root);
keytree = Newnode(c);
pre[keytree] = ch[root][1];
pushup(ch[root][1]);
pushup(root);
Splay(keytree,0);
cnt++;
}
inline void Del(){
int x = findhead();
del(x);
}
inline void del(int x){
Splay(x,0);
if(ch[x][0] == 0){
root = ch[x][1];
ch[x][0] = ch[x][1] = pre[x] = 0;
pre[root] = 0;
sz[x] = 1;
return;
}
int m = findmax(ch[root][0]);
Splay(m,root);
ch[m][1] = ch[x][1];
ch[x][0] = ch[x][1] = 0;
pre[x] = 0;
pre[ ch[m][1] ] = m;
root = m;
pre[root] = 0;
pushup(root);
sz[x] = 1;
cnt --;
}
inline void Mov(){
int tp;
scanf("%d",&tp);
int head,tail;
head = findhead();
tail = findtail();
if(tp == 1){
del(tail);
Rotateto(0,0);
Rotateto(1,root);
ch[ ch[root][1] ][0] = tail;
pre[tail] = ch[root][1];
pushup(ch[root][1]);
pushup(root);
cnt++;
}
else{
del(head);
Rotateto(cnt ,0);
Rotateto(cnt + 1,root);
ch[ ch[root][1] ][0] = head;
pre[head] = ch[root][1];
pushup(ch[root][1]);
pushup(root);
cnt++;
}
}
inline void Query(){
Rotateto(1,0);
printf("%d\n",val[root]);
}
int lazy[SIZEN],add[SIZEN];
int val[SIZEN],num[SIZEN];
};
SplayTree spt;
void solve(int n,int m,int k1,int k2){
spt.n = n;
spt.k1 = k1;
spt.k2 = k2;
spt.init();
char op[10];
while(m--){
scanf("%s",op);
if(op[0] == 'a') spt.Add();
else if(op[0] == 'r') spt.Rev();
else if(op[0] == 'i') spt.Insert();
else if(op[0] == 'd') spt.Del();
else if(op[0] == 'm') spt.Mov();
else if(op[0] == 'q') spt.Query();
}
}
int main()
{
//freopen("data.in","r",stdin);
int n,m,k1,k2,txt = 1;
while(scanf("%d%d%d%d",&n,&m,&k1,&k2)!=EOF){
if(!n && !m && !k1 && !k2) break;
printf("Case #%d:\n",txt++);
solve(n,m,k1,k2);
}
}
这道题让我想到了开始在学习线段树的一道题,【HDU 3397】
他们的共同点就是都是由一些简单的操作组合起来,使得代码量看上去非常恐怖
这道题也是我目前写过最长的代码了,能够AC也是很开心_(:з」∠)_
题目一共给了六种操作,我是一直将队首元素放在整个二叉树的最左侧
1、add x:把从1 -- k1的数都加上x
2、reverse :把从1--k2的数进行翻转
3、insert x:把x插入到第一个元素的后面
4、delete:删除掉第一个元素
5、move 1:将队尾元素删除并插入到队首
move 2:将队首元素删除并插入到队尾
6、询问队首元素的val
将以前做的操作全部结合起来在思路上应该是不难的,难点就在于debug
献上AC代码