一道裸的splay题,对我来说比较有纪念意义,毕竟是第一次上手splay,最开始用的是红书的模板,倒是功能很齐全,但是略显麻烦,所以就换成了silver__bullet的模板,发现简单多了,估计过段时间就能裸敲了,而且,等我熟悉代码的机制以后应该可以往上加一些功能了吧,下一步应该就是treap,主席树,块链,树链剖分之类的东东了吧……
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = (int)1e6 + 10;
const int INF = 0x7fffffff;
int s[maxn];
struct splaytree{
int cnt, root;
int sz[maxn], ch[maxn][2], pre[maxn];
int add[maxn], rev[maxn], minn[maxn], val[maxn];
inline void newnode(int &t, int v){
t = ++cnt;
ch[t][0] = ch[t][1] = 0;
add[t] = rev[t] = 0;
sz[t] = 1;
minn[t] = v;
val[t] = v;
}
inline void PushUp(int x){
sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1;
minn[x] = min(min(minn[ch[x][0]], minn[ch[x][1]]), val[x]);
}
inline void PushDown(int x){
if (rev[x]){
if (ch[x][0]) rev[ch[x][0]] ^= 1;
if (ch[x][1]) rev[ch[x][1]] ^= 1;
swap(ch[x][0], ch[x][1]);
rev[x] ^= 1;
}
if (add[x]){
if (ch[x][0]){
add[ch[x][0]] += add[x]; minn[ch[x][0]] += add[x]; val[ch[x][0]] += add[x];
}
if (ch[x][1]){
add[ch[x][1]] += add[x]; minn[ch[x][1]] += add[x]; val[ch[x][1]] += add[x];
}
add[x] = 0;
}
}
inline bool dir(int x){return ch[pre[x]][1] == x;}
inline void link(int x, int y, int d){
if (y) ch[y][d] = x;
if (x) pre[x] = y;
}
inline void rotate(int x){
int y = pre[x]; bool d = dir(x);
PushDown(y); PushDown(x);
link(x, pre[y], dir(y));
link(ch[x][!d], y, d);
link(y, x, !d);
PushUp(y);
}
inline void splay(int x, int goal){
PushDown(x);
while (pre[x] != goal){
if (pre[pre[x]] == goal) rotate(x);
else {
if (dir(x) == dir(pre[x])) rotate(pre[x]);
else rotate(x);
rotate(x);
}
}
PushUp(x);
if (goal == 0) root = x;
}
inline void select(int k, int goal){
int x = root;
PushDown(x);
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 int get(int ll, int rr){
select(ll - 1, 0);
select(rr + 1, root);
return ch[root][1];
}
inline void build(int l, int r, int &t, int p){
if (l > r) return;
int m = (l + r) >> 1;
newnode(t, s[m]);
build(l, m - 1, ch[t][0], t);
build(m + 1, r, ch[t][1], t);
pre[t] = p;
PushUp(t);
}
void init(int n){
cnt = root = 0;
sz[0] = ch[0][0] = ch[0][1] = pre[0] = 0;
add[0] = rev[0] = 0;
minn[0] = INF;
val[0] = INF;
newnode(root, INF);
newnode(ch[root][1], INF);
pre[cnt] = root;
sz[root] = 2;
build(1, n, ch[ch[root][1]][0], ch[root][1]);
PushUp(ch[root][1]);
PushUp(root);
}
inline void ADD(int ll, int rr, int d){
int x = get(ll, rr);
add[ch[x][0]] += d;
minn[ch[x][0]] += d;
val[ch[x][0]] += d;
PushUp(x);
PushUp(root);
}
inline void REVERSE(int ll, int rr){
int x = get(ll, rr);
rev[ch[x][0]] ^= 1;
}
inline void INSERT(int x, int val){
select(x, 0);
select(x + 1, root);
newnode(ch[ch[root][1]][0], val);
pre[ch[ch[root][1]][0]] = ch[root][1];
PushUp(ch[root][1]);
PushUp(root);
}
inline void RELOVE(int ll, int rr, int t){
int len = (rr - ll + 1); t = (t % len + len) % len;
if (t == 0) return;
REVERSE(ll, rr - t);
REVERSE(rr - t + 1, rr);
REVERSE(ll, rr);
}
inline void DELETE(int P){
int x = get(P, P);
ch[x][0] = 0;
PushUp(x);
PushUp(root);
}
inline int MIN(int ll, int rr){
int x = get(ll, rr);
return minn[ch[x][0]];
}
};
splaytree solver;
int main(){
/* #ifndef ONLINE_JUDGE
freopen("in", "rt", stdin);
#endif*/
int n, m, x, y, t;
char op[10];
while(scanf("%d", &n) == 1){
for (int i = 1; i <= n; i++)
scanf("%d", &s[i]);
solver.init(n);
scanf("%d", &m);
while(m--){
scanf("%s", op);
if (op[0] == 'A'){
scanf("%d%d%d", &x, &y, &t);
solver.ADD(x, y, t);
}else if (op[0] == 'R'){
if (op[3] == 'E'){
scanf("%d%d", &x, &y);
solver.REVERSE(x, y);
}else{
scanf("%d%d%d", &x, &y, &t);
solver.RELOVE(x, y, t);
}
}else if (op[0] == 'I'){
scanf("%d%d", &x, &t);
solver.INSERT(x, t);
}else if (op[0] == 'D'){
scanf("%d", &x);
solver.DELETE(x);
}else{
scanf("%d%d", &x, &y);
printf("%d\n", solver.MIN(x, y));
}
}
}
return 0;
}