题解 P2042 【[NOI2005]维护数列】

Creeper_LKF

2018-02-02 10:44:23

Solution

# 指针版非旋Treap 本来写的好好的,然后调指针调的......大概是我太弱了 然后就拿了@曦月__OFN 大佬的代码来对着调 然后代码就长得极其相似...... 似乎楼下题解还有一篇差不多的,但是我们不在意这些细节 指针的好处: 1. 写多了其实就好调了 1. ~~锻炼代码能力~~ 1. 方便递归 1. 可以回收内存 1. 有些操作方便 指针的坏处: 1. 同一个程序在不同机子下的表现不同(例如32位和64位) 1. 蒟蒻杀手,不方便调试 1. 分配内存略慢(当然可以开内存池) 1. 莫名RE 1. 有些操作不方便 然后接下来是代码部分,最后一段的system是用来检测内存大小: ``` #include <cstdio> #include <cctype> #include <cstdlib> using namespace std; #define MAXN 500050 #define INF 0x3f3f3f3f #define Finline __inline__ __attribute__ ((always_inline)) const int MODS = 5371321, PRI = 832211; Finline char get_char(){ static char buf[10000001], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 10000000, stdin), p1 == p2) ? EOF : *p1 ++; } inline int read(){ int num = 0; char c, sf = 1; while (!isdigit(c = get_char()) && c != '-'); if(c == '-') c = get_char(), sf = -1; while (num = num * 10 + c - 48, isdigit(c = get_char())); return num * sf; } inline void swap(int &x, int &y){ int t = x; x = y; y = t; } Finline int max(int a, int b){ int c = (a - b) >> 31; return (a & ~ c) | (b & c); } Finline int min(int a, int b){ int c = (a - b) >> 31; return (a & c) | (b & ~ c); } Finline void upmin(int &a, const int &b){ if(a > b) a = b; } Finline void upmax(int &a, const int &b){ if(a < b) a = b; } struct Node{ int size, val, wv, cov; int sum, lm, rm, sm; bool rev; Node *lc, *rc; }; int top, cnt; Node* root, *stack[MAXN]; inline void swap(Node* &x, Node* &y){ Node* t = x; x = y; y = t; } inline Node* NewNode(int val){ Node *ret; if((ret = (Node*)malloc(sizeof(Node))) == NULL) return NULL; if(cnt) cnt--; ret -> rev = false; ret -> size = 1; ret -> val = ret -> sum = ret -> sm = val; ret -> wv = rand(); ret -> cov = INF; ret -> lm = ret -> rm = max(val, 0); ret -> lc = ret -> rc = NULL; return ret; } int n, m; inline int rand(){ static int sed = 15; return sed = 1ll * sed * PRI % MODS; } inline void Del(Node *node){ if(node == NULL) return ; Del(node -> lc), Del(node -> rc); free(node); cnt++; } inline void Cover(Node *node, int val){ node -> val = val; node -> sum = (node -> size) * val; node -> lm = node -> rm = max(node -> sum, 0); node -> sm = max(node -> sum, node -> val); node -> cov = val; } inline void Reverse(Node* &node){ swap(node -> lc, node -> rc); swap(node -> lm, node -> rm); node -> rev ^= 1; } inline void Push_Up(Node *node){ bool l = node -> lc == NULL, r = node -> rc == NULL; node -> size = (l ? 0 : node -> lc -> size) + (r ? 0 : node -> rc -> size) + 1; node -> sum = (l ? 0 : node -> lc -> sum) + (r ? 0 : node -> rc -> sum) + node -> val; node -> sm = max(max((l ? -INF : node -> lc -> sm), (r ? -INF : node -> rc -> sm)), (l ? 0 : node -> lc -> rm) + (r ? 0 : node -> rc -> lm) + node -> val); node -> lm = max((l ? 0 : node -> lc -> lm), (l ? 0 : node -> lc -> sum) + (r ? 0 : node -> rc -> lm) + node -> val); node -> rm = max((r ? 0 : node -> rc -> rm), (r ? 0 : node -> rc -> sum) + (l ? 0 : node -> lc -> rm) + node -> val); } inline void Push_Down(Node *node){ if(node -> rev){ node -> rev = false; if(node -> lc != NULL) Reverse(node -> lc); if(node -> rc != NULL) Reverse(node -> rc); } if(node -> cov != INF){ if(node -> lc != NULL) Cover(node -> lc, node -> cov); if(node -> rc != NULL) Cover(node -> rc, node -> cov); node -> cov = INF; } } inline Node* Merge(Node* x, Node* y){ if(x != NULL) Push_Down(x); if(y != NULL) Push_Down(y); if(x == NULL || y == NULL) return x == NULL ? y : x; if(x -> wv < y -> wv){ x -> rc = Merge(x -> rc, y); Push_Up(x); return x; } else { y -> lc = Merge(x, y -> lc); // if(y == y -> lc) printf("Dead in line %d of %d\n", __LINE__, y -> wv); Push_Up(y); return y; } } inline void Split(Node* node, int k, Node* &x, Node* &y){ if(node == NULL){ x = y = NULL; return; } Push_Down(node); if((node -> lc == NULL ? 0 : node -> lc -> size) >= k){ y = node; Split(node -> lc, k, x, node -> lc); } else { x = node; Split(node -> rc, k - 1 - (node -> lc == NULL ? 0 : node -> lc -> size), node -> rc, y); } Push_Up(node); } int main(){ // freopen("in.in", "r", stdin); // freopen("out.out", "w", stdout); n = read(), m = read(); for(int i = 1; i <= n; i++){ int val = read(); Node *p = NewNode(val), *tmp = NULL; if(top) stack[top] -> rc = p; p -> lc = tmp, stack[++top] = p; } while(top) Push_Up(stack[top--]); root = stack[1]; while(m--){ char cons; while(!isalpha(cons = get_char())); if(cons == 'I'){ int st = read(), tot = read(); for(int i = 1; i <= tot; i++){ int val = read(); Node *p = NewNode(val), *tmp = NULL; while(cnt && stack[top] != NULL && stack[top] -> wv > p -> wv){ Push_Up(stack[top]); tmp = stack[top]; stack[top--] = NULL; } if(top) stack[top] -> rc = p; p -> lc = tmp, stack[++top] = p; } Node *ls = NULL, *rs = NULL, *tmp; while(top) Push_Up(stack[top--]); tmp = stack[1]; Split(root, st, ls, rs); root = Merge(Merge(ls, tmp), rs); } else if(cons == 'D'){ int st = read(), k = read(); Node *ls = NULL, *rs = NULL, *xs = NULL, *ys = NULL; Split(root, st - 1, ls, rs); Split(rs, k, xs, ys); root = Merge(ls, ys); cnt += xs == NULL ? 0 : xs -> size; Del(xs); } else if(cons == 'R'){ int st = read(), k = read(); Node *ls = NULL, *rs = NULL, *xs = NULL, *ys = NULL; Split(root, st - 1, ls, rs); Split(rs, k, xs, ys); Reverse(xs); root = Merge(ls, Merge(xs, ys)); } else if(cons == 'G'){ while(!isspace(get_char())); int st = read(), k = read(); Node *ls = NULL, *rs = NULL, *xs = NULL, *ys = NULL; Split(root, st - 1, ls, rs); Split(rs, k, xs, ys); if(xs == NULL) puts("0"); else printf("%d\n", xs -> sum); root = Merge(ls, Merge(xs, ys)); } else { cons = get_char(), cons = get_char(); while(!isspace(get_char())); if(cons == 'X') printf("%d\n", root -> sm); else { int st = read(), k = read(), val = read(); Node *ls = NULL, *rs = NULL, *xs = NULL, *ys = NULL; Split(root, st - 1, ls, rs); Split(rs, k, xs, ys); Cover(xs, val); root = Merge(ls, Merge(xs, ys)); } } } // Debug Get Running Memery // system("wmic process where name=\"a.exe\" get WorkingSetSize"); return 0; } ```