数据比较恶心的一道题,主要是REVOLVE的数据可以超过长度,而且还可能是负数,爱神的思路比较巧妙,利用模代数系统各种数据都等价到[0, len-1],这样就可以很方便的处理了。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <utility>
#include <ctime>
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
const int MAXN(200010);
const int MAXM(10010);
const int MAXE(10010);
const int MAXH(19);
const int INFI((INT_MAX-1) >> 1);
const int MOD(10000);
const ULL BASE(31);
const LL LIM(10000000);
const int INV(-10000);
int arr[MAXN];
struct SPLAY_TREE
{
struct NODE
{
int num, size, flag1, flag2;
int mi;
NODE *fa;
NODE *ch[2];
};
NODE pool[MAXN];
NODE *root, *NIL, *rear;
inline void push_up(NODE *sour) //一定要注意NIL节点对push_up的影响
{
sour->size = sour->ch[0]->size+sour->ch[1]->size+1;
sour->mi = min(sour->num, min(sour->ch[0]->mi, sour->ch[1]->mi));
}
inline void updata_add(NODE *sour, int v)
{
if(sour == NIL) return;
sour->mi += v;
sour->num += v;
sour->flag1 += v;
}
inline void updata_rev(NODE *sour)
{
if(sour == NIL) return;
swap(sour->ch[0], sour->ch[1]);
sour->flag2 ^= 1;
}
void push_down(NODE *sour) //和线段树的push_down一样,是对子节(注意不是本节点)进行更新
{
if(sour->flag1)
{
updata_add(sour->ch[0], sour->flag1);
updata_add(sour->ch[1], sour->flag1);
sour->flag1 = 0;
}
if(sour->flag2)
{
updata_rev(sour->ch[0]);
updata_rev(sour->ch[1]);
sour->flag2 = 0;
}
}
void initNIL()
{
NIL->ch[0] = NIL->ch[1] = NIL->fa = NIL;
NIL->mi = INFI;
NIL->size = 0;
}
void init(int n)
{
NIL = pool;
initNIL();
rear = pool+1;
newnode(root, NIL, -100000); //插入无穷小
newnode(root->ch[1], root, 100000); //插入无穷大
build_tree(root->ch[1]->ch[0], root->ch[1], 1, n); //建树
push_up(root->ch[1]);
push_up(root);
}
void newnode(NODE *&sour, NODE *f, int num)
{
sour = rear++;
sour->num = sour->mi = num;
sour->size = 1;
sour->flag1 = sour->flag2 = 0;
sour->fa = f;
sour->ch[0] = sour->ch[1] = NIL;
}
void build_tree(NODE *&sour, NODE *f, int l, int r)
{
if(l > r)
return;
int m = (l+r) >> 1;
newnode(sour, f, arr[m]);
build_tree(sour->ch[0], sour, l, m-1);
build_tree(sour->ch[1], sour, m+1, r);
push_up(sour);
}
void rotate(NODE *sour, int flag)
{
NODE *f = sour->fa;
push_down(f);
push_down(sour);
f->ch[!flag] = sour->ch[flag];
sour->ch[flag]->fa = f;
sour->fa = f->fa;
if(f->fa != NIL)
f->fa->ch[f->fa->ch[1] == f] = sour;
sour->ch[flag] = f;
f->fa = sour;
push_up(f);
}
void splay(NODE *sour, NODE *goal)
{
push_down(sour);
while(sour->fa != goal)
{
if(sour->fa->fa == goal)
rotate(sour, sour->fa->ch[0] == sour);
else
{
NODE *f = sour->fa;
int flag = (f->fa->ch[0] == f);
if(f->ch[flag] == sour)
rotate(sour, !flag);
else
rotate(f, flag);
rotate(sour, flag);
}
}
push_up(sour);
if(goal == NIL)
root = sour;
}
NODE *select(NODE *sour, int r)
{
while(true)
{
push_down(sour);
if(r == sour->ch[0]->size+1)
break;
if(r <= sour->ch[0]->size)
sour = sour->ch[0];
else
{
r -= sour->ch[0]->size+1;
sour = sour->ch[1];
}
}
return sour;
}
void ADD(int pos1, int pos2, int value)
{
NODE *tp;
tp = select(root, pos1);
splay(tp, NIL);
tp = select(root, pos2+2);
splay(tp, root);
updata_add(tp->ch[0], value);
push_up(root->ch[1]);
push_up(root);
}
void REVERSE(int pos1, int pos2)
{
NODE *tp;
tp = select(root, pos1);
splay(tp, NIL);
tp = select(root, pos2+2);
splay(tp, root);
updata_rev(tp->ch[0]);
push_up(root->ch[1]);
push_up(root);
}
void REVOLVE(int pos1, int pos2, int T)
{
NODE *tp1, *tp2;
tp1 = select(root, pos1);
splay(tp1, NIL);
tp1 = select(root, pos2-T+2);
splay(tp1, root);
tp2 = tp1->ch[0];
tp1->ch[0] = NIL;
push_up(root->ch[1]);
push_up(root);
tp1 = select(root, pos1+T);
splay(tp1, NIL);
tp1 = select(root, pos1+T+1);
splay(tp1, root);
tp1->ch[0] = tp2;
tp2->fa = tp1;
push_up(root->ch[1]);
push_up(root);
}
void INSERT(int pos, int value)
{
NODE *tp;
tp = select(root, pos+1);
splay(tp, NIL);
tp = select(root, pos+2);
splay(tp, root);
newnode(tp->ch[0], tp, value);
push_up(root->ch[1]);
push_up(root);
}
void DELETE(int pos)
{
NODE *tp;
tp = select(root, pos);
splay(tp, NIL);
tp = select(root, pos+2);
splay(tp, root);
tp->ch[0] = NIL;
push_up(root->ch[1]);
push_up(root);
}
int MIN(int pos1, int pos2)
{
NODE *tp;
tp = select(root, pos1);
splay(tp, NIL);
tp = select(root, pos2+2);
splay(tp, root);
return tp->ch[0]->mi;
}
};
SPLAY_TREE spt;
char str[10];
int main()
{
int n;
while(~scanf("%d", &n))
{
for(int i = 1; i <= n; ++i)
scanf("%d", arr+i);
spt.init(n);
int m;
scanf("%d", &m);
int op1, op2, op3;
for(int i = 0; i < m ; ++i)
{
scanf("%s", str);
if(str[0] == 'A')
{
scanf("%d%d%d", &op1, &op2, &op3);
spt.ADD(op1, op2, op3);
}
else if(str[0] == 'R' && str[3] == 'E')
{
scanf("%d%d", &op1, &op2);
spt.REVERSE(op1, op2);
}
else if(str[0] == 'R' && str[3] == 'O')
{
scanf("%d%d%d", &op1, &op2, &op3);
int tlen = op2-op1+1;
spt.REVOLVE(op1, op2, (op3%tlen+tlen)%tlen);
}
else if(str[0] == 'I')
{
scanf("%d%d", &op1, &op2);
spt.INSERT(op1, op2);
}
else if(str[0] == 'D')
{
scanf("%d", &op1);
spt.DELETE(op1);
}
else
{
scanf("%d%d", &op1, &op2);
printf("%d\n", spt.MIN(op1, op2));
}
}
}
return 0;
}