題解【bzoj1251 序列終結者】
阿新 • • 發佈:2018-12-23
Description
維護三個操作:區間加,區間翻轉,區間求最大值。\(n \leq 50000\)
Solution
fhqtreap大法好!
模板題(我是不會告訴你這篇題解是用來存個程式碼的
Code
#include <bits/stdc++.h> using namespace std; const int INF = 2147483647; const int N = 50050; int n, m; struct node { int d, rnd, Mx, add, rev, siz; node *ch[2]; inline void upd() { int sizz = 1, MX = d; if(ch[0]) sizz += ch[0]->siz, MX = max(MX, ch[0]->Mx); if(ch[1]) sizz += ch[1]->siz, MX = max(MX, ch[1]->Mx); siz = sizz; Mx = MX; } inline void push() { if(add) { if(ch[0]) { ch[0]->d += add, ch[0]->Mx += add, ch[0]->add += add; } if(ch[1]) { ch[1]->d += add, ch[1]->Mx += add, ch[1]->add += add; } upd(); add = 0; } if(rev) { swap(ch[0], ch[1]); if(ch[0]) ch[0]->rev ^= 1; if(ch[1]) ch[1]->rev ^= 1; rev = 0; } } }pool[N], *cur = pool, *root; inline int siz(node *p) { if(p) return p->siz; return 0; } inline node *newnode(int d) { node *ret = cur++; ret->siz = 1, ret->d = ret->Mx = d, ret->add = ret->rev = 0; ret->rnd = rand(); ret->ch[0] = ret->ch[1] = 0; return ret; } inline node *merge(node *p, node *q) { if(!p) return q; if(!q) return p; if(p->rnd < q->rnd) { p->push(); p->ch[1] = merge(p->ch[1], q); p->upd(); return p; } if(p->rnd >= q->rnd) { q->push(); q->ch[0] = merge(p, q->ch[0]); q->upd(); return q; } } inline void split(node *r, int k, node *&p, node *&q) { if(!r) { p = q = NULL; return ; } r->push(); if(siz(r->ch[0]) < k) p = r, split(r->ch[1], k - siz(r->ch[0]) - 1, r->ch[1], q); else q = r, split(r->ch[0], k, p, r->ch[0]); r->upd(); } int main() { srand((unsigned long long)new char); scanf("%d %d", &n, &m); root = newnode(0); for(int i = 2; i <= n; i++) root = merge(root, newnode(0)); for(int i = 1; i <= m; i++) { int op, l, r, x; node *p, *q, *s; scanf("%d %d %d", &op, &l, &r); split(root, l - 1, p, q); split(q, r - l + 1, q, s); if(op == 1) scanf("%d", &x), q->add += x, q->d += x, q->Mx += x; if(op == 2) q->rev ^= 1; if(op == 3) printf("%d\n", q->Mx); root = merge(p, merge(q, s)); } return 0; }