[代码] bzoj 1500 维修数列(无旋treap)
- 传送门 -
http://www.lydsy.com/JudgeOnline/problem.php?id=1500
1500: [NOI2005]维修数列
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 15301 Solved: 5063
Description
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
Sample Input
9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM
Sample Output
-1
10
1
10
HINT
- 代码 -
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <ctime>
#include <cstdlib>
#define pii pair<int, int>
#define mp make_pair
#define ls C[rt][0]
#define rs C[rt][1]
using namespace std;
template <typename ty> void read(ty &x) {
x = 0; int f = 1; char ch = getchar();
while (ch > '9' || ch < '0') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x*10 + ch - '0'; ch = getchar(); }
x *= f;
}
template <typename ty> ty Max(ty a, ty b) { return a > b ? a : b; }
template <typename ty> ty Min(ty a, ty b) { return a < b ? a : b; }
template <typename ty> int Chkmin(ty a, ty b) { return a > b ? a = b, 1 : 0; }
template <typename ty> int Chkmax(ty a, ty b) { return a < b ? a = b, 1 : 0; }
typedef long long LL;
typedef double db;
const int inf = 0x7fffffff;
const int N = 5e5 + 160;
int V[N], C[N][2], S[N], STK[N], KEY[N];
int TAG[N], REV[N], A[N], Q[4000016];
int LM[N], RM[N], TM[N], T[N];
int root, n, m, sz, tot;
int pos, t, c;
char OP[160];
void pushtag(int rt, int val) {
if (!rt) return;
V[rt] = val;
T[rt] = S[rt] * val;
LM[rt] = RM[rt] = TM[rt] = Max(val, val * S[rt]);
TAG[rt] = 1;
}
void pushrev(int rt) {
if (!rt) return;
swap(C[rt][0], C[rt][1]);
swap(LM[rt], RM[rt]);
REV[rt] ^= 1;
}
void pushup(int rt) {
if (!rt) return;
S[rt] = S[ls] + S[rs] + 1;
T[rt] = T[ls] + T[rs] + V[rt];
LM[rt] = Max(LM[ls], T[ls] + V[rt] + Max(LM[rs], 0));
RM[rt] = Max(RM[rs], T[rs] + V[rt] + Max(RM[ls], 0));
TM[rt] = Max(TM[ls], Max(TM[rs], V[rt] + Max(LM[rs], 0) + Max(RM[ls], 0)));
}
void pushdown(int rt) {
if (!rt) return;
if (TAG[rt]) {
pushtag(ls, V[rt]);
pushtag(rs, V[rt]);
TAG[rt] = REV[rt] = 0;
}
if (REV[rt]) {
pushrev(ls);
pushrev(rs);
REV[rt] = 0;
}
}
int new_node() {
int a, b;
read(a);
if (tot) b = Q[tot--];
else b = ++sz;
V[b] = a; KEY[b] = rand();
C[b][0] = C[b][1] = 0;
S[b] = 1; TAG[b] = REV[b] = 0;
LM[b] = RM[b] = TM[b] = T[b] = a;
return b;
}
int build(int s) {
int lst = 0, top = 0;
for (int i = 1; i <= s; ++ i) {
int tmp = new_node(); lst = 0;
while (top && KEY[tmp] < KEY[STK[top]]) {
pushup(STK[top]);
lst = STK[top];
STK[top--] = 0;
}
if (lst) C[tmp][0] = lst;
if (top) C[STK[top]][1] = tmp;
STK[++top] = tmp;
}
while (top) pushup(STK[top--]);
return STK[1];
}
pii split(int rt, int k) {
if (!rt) return mp(0, 0);
pii tmp;
pushdown(rt);
if (k > S[C[rt][0]]) {
tmp = split(C[rt][1], k - S[C[rt][0]] - 1);
C[rt][1] = tmp.first; pushup(rt); tmp.first = rt;
}
else {
tmp = split(C[rt][0], k);
C[rt][0] = tmp.second; pushup(rt); tmp.second = rt;
}
return tmp;
}
int merge(int ra, int rb) {
if (!ra) return rb;
if (!rb) return ra;
pushdown(ra);
pushdown(rb);
if (KEY[ra] < KEY[rb]) {
C[ra][1] = merge(C[ra][1], rb);
pushup(ra); return ra;
}
else {
C[rb][0] = merge(ra, C[rb][0]);
pushup(rb); return rb;
}
}
void recycle(int rt) {
if (!rt) return;
Q[++tot] = rt;
recycle(C[rt][0]);
recycle(C[rt][1]);
}
void work1() {
read(pos); read(t);
pii a = split(root, pos);
root = merge(a.first, merge(build(t), a.second));
}
void work2() {
read(pos); read(t);
pii a = split(root, pos - 1);
pii b = split(a.second, t);
recycle(b.first);
root = merge(a.first, b.second);
}
void work3() {
read(pos); read(t); read(c);
if (!t) return;
pii a = split(root, pos - 1);
pii b = split(a.second, t);
pushtag(b.first, c);
root = merge(a.first, merge(b.first, b.second));
}
void work4() {
read(pos); read(t);
if (!t) return;
pii a = split(root, pos - 1);
pii b = split(a.second, t);
pushrev(b.first);
root = merge(a.first, merge(b.first, b.second));
}
void work5() {
read(pos); read(t);
if (!t) { printf("0\n"); return; }
pii a = split(root, pos - 1);
pii b = split(a.second, t);
printf("%d\n", T[b.first]);
root = merge(a.first, merge(b.first, b.second));
}
void work6() { printf("%d\n", TM[root]); }
int main () {
read(n); read(m);
LM[0] = RM[0] = TM[0] = V[0] = -inf;
root = build(n);
for (int i = 1; i <= m; ++ i) {
scanf("%s", OP);
if (OP[0] == 'I') work1();
if (OP[0] == 'D') work2();
if (OP[2] == 'K') work3();
if (OP[0] == 'R') work4();
if (OP[0] == 'G') work5();
if (OP[2] == 'X') work6();
}
return 0;
}