基本包括了Splay Tree的所有操作,插入,删除,右移,翻转,区间更新,区间查询。学习Splay Tree推荐一个博客,FZU_Jason。这道题基本上就是抄的他的。。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define CLR(a, b) memset(a, b, memset(a))
using namespace std;
const int N = 200010;
const int INF = 0x7FFFFFFF;
struct SplayTree
{
int size, root, top;
int st[N], a[N];
int ch[N][2], pre[N], key[N], num[N];
//num 当前根下节点个数
int add[N], mini[N];
bool flip[N];
inline void PushUp(int x)
{
num[x] = num[ch[x][0]] + num[ch[x][1]] + 1;
mini[x] = min(mini[ch[x][0]], mini[ch[x][1]]);
mini[x] = min(mini[x], key[x]);
}
inline void PushDown(int x)
{
int L, R;
L = ch[x][0];R = ch[x][1];
if(add[x])
{
if(L)
{
add[L] += add[x];
key[L] += add[x];
mini[L] += add[x];
}
if(R)
{
add[R] += add[x];
key[R] += add[x];
mini[R] += add[x];
}
add[x] = 0;
}
if(flip[x])
{
flip[L] ^= true;
flip[R] ^= true;
swap(ch[x][0], ch[x][1]);
flip[x] = false;
}
}
void NewNode(int &x, int father, int val)
{
if(top != -1)
x = st[top --];
else
x = ++size;
ch[x][0] = ch[x][1] = add[x] = 0;
pre[x] = father;
key[x] = mini[x] = val;
num[x] = 1;
flip[x] = false;
}
void Build(int &x, int L, int R, int father)
{
if(L <= R)
{
int mid = (L + R) >> 1;
NewNode(x, father, a[mid]);
Build(ch[x][0], L, mid - 1, x);
Build(ch[x][1], mid + 1, R, x);
PushUp(x);
}
}
void Init(int n)
{
root = size = 0;
top = -1;
flip[0] = false;
ch[0][0] = ch[0][1] = pre[0] = num[0] = add[0] = 0;
key[0] = mini[0] = INF;
NewNode(root, 0, INF);
NewNode(ch[root][1], root, INF);
Build(ch[ch[root][1]][0], 1, n, ch[root][1]);
PushUp(ch[root][1]);
PushUp(root);
}
void Rotate(int x, int kind)
{
int y = pre[x];
PushDown(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;
PushUp(y);
}
void Splay(int r, int goal)
{
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);
}
}
//PushUp(r);
if(goal == 0) root = r;
}
/*
void Rotate(int x, int kind) {
int y, z;
y = pre[x];
z = pre[y];
PushDown(y);
ch[y][!kind] = ch[x][kind];
pre[ch[x][kind]] = y;
ch[z][ch[z][1] == y] = x;
pre[x] = z;
ch[x][kind] = y;
pre[y] = x;
PushUp(y);
}
void Splay(int x, int goal) {
if (x != goal) {
PushDown(x);
while (pre[x] != goal) {
if (ch[pre[x]][0] == x)
Rotate(x, 1);
else
Rotate(x, 0);
}
PushUp(x);
if (!goal)
root = x;
}
}
*/
int Select(int k)
{
int x;
PushDown(root);
for(x = root; num[ch[x][0]] + 1 != k;)
{
if(num[ch[x][0]] + 1 > k)
x = ch[x][0];
else
k -= num[ch[x][0]] + 1, x = ch[x][1];
PushDown(x);
}
return x;
}
void Add(int x, int y, int val)
{
int t;
x = Select(x - 1);
y = Select(y + 1);
Splay(x, 0);
Splay(y, x);
t = ch[y][0];
add[t] += val;
key[t] += val;
mini[t] += val;
PushUp(y);
PushUp(x);
}
void Flip(int x, int y)
{
x = Select(x - 1);
y = Select(y + 1);
Splay(x, 0);
Splay(y, x);
flip[ch[y][0]] ^= true;
}
void Revolve(int x, int y, int t)
{
int cnt = y - x + 1;
t %= cnt;
if(t < 0)
t += cnt;
if(t)
{
Flip(x, y - t);
Flip(y - t + 1, y);
Flip(x, y);
}
}
void Insert(int x, int val)
{
int a, b;
a = Select(x);
b = Select(x + 1);
Splay(a, 0);
Splay(b, a);
NewNode(ch[b][0], b, val);
PushUp(b);
PushUp(a);
}
void Delete(int x)
{
int a, b;
a = Select(x - 1);
b = Select(x + 1);
Splay(a, 0);
Splay(b, a);
st[++ top] = ch[b][0];
ch[b][0] = 0;
PushUp(b);
PushUp(a);
}
int MIN(int x, int y)
{
x = Select(x - 1);
y = Select(y + 1);
Splay(x, 0);
Splay(y, x);
return mini[ch[y][0]];
}
}spt;
int main() {
char cmd[18];
int n, q, i;
int x, y, val;
while (~scanf("%d", &n)) {
for (i = 1; i <= n; i++)
scanf("%d", &spt.a[i]);
spt.Init(n);
scanf("%d", &q);
while (q--) {
scanf(" %s", cmd);
if (strcmp(cmd, "ADD") == 0) {
scanf("%d%d%d", &x, &y, &val);
spt.Add(x + 1, y + 1, val);
} else if (strcmp(cmd, "REVERSE") == 0) {
scanf("%d%d", &x, &y);
spt.Flip(x + 1, y + 1);
} else if (strcmp(cmd, "REVOLVE") == 0) {
scanf("%d%d%d", &x, &y, &val);
spt.Revolve(x + 1, y + 1, val);
} else if (strcmp(cmd, "INSERT") == 0) {
scanf("%d%d", &x, &val);
spt.Insert(x + 1, val);
} else if (strcmp(cmd, "DELETE") == 0) {
scanf("%d", &x);
spt.Delete(x + 1);
} else {
scanf("%d%d", &x, &y);
printf("%d\n", spt.MIN(x + 1, y + 1));
}
}
}
return 0;
}