http://www.lydsy.com/JudgeOnline/problem.php?id=1500
很磨人的题,如果对splay的push_up和push_down理解不透彻的话debug过程会很痛苦的,一定要注意及时把信息更新的根节点,还有就是这题要求至少选择一个数。
/* 30 1000 -505 467 -773 -521 808 -690 939 -962 -490 -688 -878 254 -811 120 -866 132 -771 830 -761 139 -692 -336 63 -410 486 -828 922 981 738 -94 DELETE 3 5 GET-SUM 10 9 GET-SUM 10 9 INSERT 22 6 -145 928 -886 399 403 -252 GET-SUM 27 3 GET-SUM 18 10 DELETE 7 6 GET-SUM 12 7 MAKE-SAME 9 7 -742 INSERT 5 7 -758 920 -96 417 -813 136 -899 DELETE 22 5 INSERT 5 9 -4 893 -312 -22 -72 641 727 130 613 REVERSE 18 1 MAKE-SAME 31 5 807 MAX-SUM MAKE-SAME 6 6 -939 REVERSE 1 36 INSERT 36 9 -965 -750 -344 -27 511 762 -34 462 907 MAKE-SAME 11 7 864 DELETE 8 7 GET-SUM 5 7 REVERSE 1 17 REVERSE 7 21 MAX-SUM */ #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(500015); 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 value[MAXN]; struct SPLAY_TREE { struct NODE { int num, size, flag1, flag2; int lsum, rsum, msum, sum; NODE *fa; NODE *ch[2]; }; NODE pool[MAXN]; NODE *rec[MAXN]; int top; NODE *root, *NIL, *rear, *ll, *rl; inline void push_up(NODE *sour) //一定要注意NIL节点对push_up的影响 { NODE *lc = sour->ch[0], *rc = sour->ch[1]; sour->size = lc->size+rc->size+1; sour->sum = lc->sum+rc->sum+sour->num; sour->msum = max( max(lc->msum, rc->msum), max(max(lc->rsum+sour->num, rc->lsum+sour->num), max(lc->rsum+rc->lsum+sour->num, sour->num) ) ); sour->lsum = max(lc->lsum, max(lc->sum+sour->num, lc->sum+sour->num+rc->lsum)); sour->rsum = max(rc->rsum, max(rc->sum+sour->num, rc->sum+sour->num+lc->rsum)); } inline void updata_same(NODE *sour, int v) { if(sour == NIL) return; sour->sum = sour->size*v; sour->lsum = sour->rsum = sour->msum = (v > 0? v*sour->size: v); sour->num = v; sour->flag1 = v; } inline void updata_rev(NODE *sour) { if(sour == NIL) return; swap(sour->ch[0], sour->ch[1]); swap(sour->lsum, sour->rsum); sour->flag2 ^= 1; } void push_down(NODE *sour) //和线段树的push_down一样,是对子节(注意不是本节点)进行更新 { if(sour->flag1 != INV) { updata_same(sour->ch[0], sour->flag1); updata_same(sour->ch[1], sour->flag1); sour->flag1 = INV; } 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->num = NIL->lsum = NIL->rsum = NIL->msum = -1000000; //为了防止NIL对push_up造成影响 NIL->size = NIL->sum = 0; //为了防止NIL对push_up造成影响 } void init(int n) { NIL = pool; initNIL(); rear = pool+1; top = 0; 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) { if(top) sour = rec[--top]; else sour = rear++; sour->num = num; sour->size = 1; sour->flag1 = INV; sour->flag2 = 0; sour->lsum = sour->rsum = sour->msum = sour->sum = num; 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, value[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 FREE(NODE *sour) { if(sour == NIL) return; FREE(sour->ch[0]); FREE(sour->ch[1]); rec[top++] = sour; } void INSERT(int pos, int n) { NODE *tp; tp = select(root, pos+1); splay(tp, NIL); tp = select(root, pos+2); splay(tp, root); build_tree(tp->ch[0], tp, 1, n); push_up(root->ch[1]); push_up(root); } void DELETE(int pos, int n) { NODE *tp; tp = select(root, pos); splay(tp, NIL); tp = select(root, pos+1+n); splay(tp, root); FREE(tp->ch[0]); tp->ch[0] = NIL; push_up(root->ch[1]); push_up(root); } void MAKE_SAME(int pos, int n, int c) { NODE *tp; tp = select(root, pos); splay(tp, NIL); tp = select(root, pos+1+n); splay(tp, root); updata_same(tp->ch[0], c); push_up(root->ch[1]); push_up(root); } void REVERSE(int pos, int n) { NODE *tp; tp = select(root, pos); splay(tp, NIL); tp = select(root, pos+1+n); splay(tp, root); updata_rev(tp->ch[0]); push_up(root->ch[1]); push_up(root); } int GET_SUM(int pos, int n) { NODE *tp; tp = select(root, pos); splay(tp, NIL); tp = select(root, pos+1+n); splay(tp, root); return tp->ch[0]->sum; } int MAX_SUM() { NODE *tp; tp = select(root, 1); splay(tp, NIL); tp = select(root, root->size); splay(tp, root); return tp->ch[0]->msum; } }; SPLAY_TREE spt; char str[20]; int main() { int n, m; // freopen("d:\\out.txt", "w", stdout); while(~scanf("%d%d", &n, &m)) { for(int i = 1; i <= n; ++i) scanf("%d", value+i); spt.init(n); int pos, tn, temp; for(int j = 0; j < m; ++j) { // spt.debug(); scanf("%s", str); if(strcmp(str, "INSERT") == 0) { scanf("%d%d", &pos, &tn); for(int i = 1; i <= tn; ++i) scanf("%d", value+i); spt.INSERT(pos, tn); } else if(strcmp(str, "DELETE") == 0) { scanf("%d%d", &pos, &tn); spt.DELETE(pos, tn); } else if(strcmp(str, "MAKE-SAME") == 0) { scanf("%d%d%d", &pos, &tn, &temp); spt.MAKE_SAME(pos, tn, temp); } else if(strcmp(str, "REVERSE") == 0) { scanf("%d%d", &pos, &tn); spt.REVERSE(pos, tn); } else if(strcmp(str, "GET-SUM") == 0) { scanf("%d%d", &pos, &tn); printf("%d\n", spt.GET_SUM(pos, tn)); } else printf("%d\n", spt.MAX_SUM()); } } return 0; }