这题比较裸, 一看就是伸展树。就是有些小细节要注意, 为了避免反转时, 指针变化, 我是直接先把前面一段接在后面, 这样就不会出现指针变化的问题。 敲好以后一直TLE, 调了半天, 发现添加的时候我既然还是用n来添加= =(n表示现在的结点数,最后添加一个变量tn表示到现在为止出现过的结点数)。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200007;
#define KT ch[ch[root][1]][0]
int root, ch[N][2], fa[N], sz[N];
int n, m, k1, k2, id, tn;
bool rev[N];
int sum[N], num[N];
void build()
{
fa[0] = fa[n + 1] = 0;
sz[n + 1] = n + 2;
ch[n + 1][1] = 1;
fa[1] = n + 1;
sz[1] = n + 1;
for(int i = 2; i <= n; i++)
{
fa[i] = i - 1;
ch[i - 1][1] = i;
sz[i]= n + 2 - i;
}
fa[n + 2] = n;
sz[n + 2] = 1;
ch[n][1] = n + 2;
}
void init()
{
sz[0] = 0;
memset(ch, 0, sizeof(ch));
num[0] = num[n + 1] = num[n + 2] = 0;
for(int i =1; i <= n; i++)
scanf("%d", num + i);
memset(rev, false, sizeof(rev));
memset(sum, 0, sizeof(sum));
root = n + 1;
id = 2;
build();
}
inline void pushup(int x)
{
sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1;
}
inline void pushdown(int x)
{
if(rev[x])
{
rev[ch[x][0]] = !rev[ch[x][0]];
rev[ch[x][1]] = !rev[ch[x][1]];
swap(ch[x][0], ch[x][1]);
rev[x] = !rev[x];
}
if(sum[x])
{
sum[ch[x][0]] += sum[x];
sum[ch[x][1]] += sum[x];
num[ch[x][0]] += sum[x];
num[ch[x][1]] += sum[x];
sum[x] = 0;
}
}
inline void rotate(int x, bool f)
{
int y = fa[x];
int z = fa[y];
pushdown(y);
pushdown(x);
ch[y][!f] = ch[x][f];
fa[ch[x][f]] = y;
fa[x] = z;
if(z)
ch[z][ch[z][1] == y] = x;
ch[x][f] = y;
fa[y] = x;
pushup(y);
}
void splay(int x, int g)
{
int y = fa[x];
pushdown(x);
while(y != g)
{
int z = fa[y];
bool f = (ch[y][0] == x);
if(z != g && f == (ch[z][0] == y))
rotate(y, f);
rotate(x, f);
y = fa[x];
}
pushup(x);
if(g == 0)
root = x;
}
void rotateto(int k, int g)
{
int x = root;
pushdown(x);
while(sz[ch[x][0]] != k)
{
if(k < sz[ch[x][0]])
x = ch[x][0];
else
{
k -= sz[ch[x][0]] + 1;
x = ch[x][1];
}
pushdown(x);
}
splay(x, g);
}
void lin(int b)
{
rotateto(0, 0);
b -= n + 1;
rotateto(b + 1, root);
int temp = KT;
KT = 0;
sz[ch[root][1]] -= sz[temp];
sz[root] -= sz[temp];
id = id - sz[temp];
fa[temp] = 0;
rotateto(n - sz[temp], 0);
rotateto(n + 1 - sz[temp], root);
KT = temp;
fa[temp] = ch[root][1];
sz[ch[root][1]] += sz[temp];
sz[root] += sz[temp];
}
void add(int c)
{
int b = id + k2 - 1;
if(b > n + 1)
lin(b);
int a = id;
b = id + k2 - 1;
rotateto(a - 2, 0);
rotateto(b, root);
sum[KT] += c;
num[KT] += c;
}
void reve()
{
int b = id + k1 - 1;
if(b > n + 1)
lin(b);
b = id + k1 - 1;
int a = id;
rotateto(a - 2, 0);
rotateto(b, root);
rev[KT] = !rev[KT];
}
void insert(int c)
{
rotateto(id - 1, 0);
rotateto(id, root);
n++;
tn++;
num[tn + 2] = c;
sum[tn + 2] = rev[tn + 2] = 0;
sz[tn + 2] = 1;
ch[tn + 2][1] = ch[tn + 2][0] = 0;
fa[tn + 2] = ch[root][1];
KT = tn + 2;
sz[ch[root][1]]++;
sz[root]++;
}
void del()
{
rotateto(id - 2, 0);
rotateto(id, root);
fa[KT] = 0;
KT = 0;
sz[ch[root][1]]--;
sz[root]--;
if(id == n + 1)
id = 2;
n--;
}
void move(int a)
{
if(a == 1)
{
if(id == 2)
id = n + 1;
else
id--;
}
else
{
if(id == n + 1)
id = 2;
else
id++;
}
}
int que()
{
rotateto(id - 2, 0);
rotateto(id, root);
return num[KT];
}
int main()
{
//freopen("in.txt", "r", stdin);
int C = 1;
while(scanf("%d%d%d%d", &n, &m, &k1, &k2), n || m || k1 || k2)
{
init();
tn = n;
printf("Case #%d:\n", C++);
while(m--)
{
char s[20];
scanf("%s", s);
int a;
if(s[0] == 'a')
{
scanf("%d", &a);
add(a);
}
else if(s[0] == 'r')
reve();
else if(s[0] == 'i')
{
scanf("%d", &a);
insert(a);
}
else if(s[0] == 'd')
del();
else if(s[0] == 'm')
{
scanf("%d", &a);
move(a);
}
else
printf("%d\n", que());
}
}
return 0;
}