数据比较恶心的一道题,主要是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; }