【bzoj1500】[NOI2005]维修数列
题目描述:

输入:
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
输出:
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
样例输入:
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
样例输出:
-1
10
1
10
题解:
splay果体。
immortalCO:用treap更快,而且还更好写。
反正这题机房里的其他神犇都是1A+差不多1h写完的,而我蒟蒻调了整整三天才调出来。QAQ
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
#ifdef CT
#define debug(...) printf(__VA_ARGS__)
#else
#define debug(...)
#endif
#define R register
#define getc() (S == T&&(T = (S = B) + fread(B, 1, 1<<15, stdin), S == T)?EOF: * S ++ )
#define gmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define gmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
char B[1<<15], * S = B, * T = B;
inline int FastIn()
{
R char ch;R int cnt = 0;R bool minus = 0;
while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
ch == '-' ?minus = 1:cnt = ch-'0';
while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
return minus?-cnt:cnt;
}
#define maxn 1000010
int fa[maxn], ch[maxn][2], a[maxn], size[maxn], cnt;
int sum[maxn], lmx[maxn], rmx[maxn], mx[maxn], v[maxn], id[maxn], root;
bool rev[maxn], tag[maxn];
inline void swap(int &a, int &b)
{
R int tmp = a;a = b;b = tmp;
}
inline void update(R int x)
{
R int ls = ch[x][0], rs = ch[x][1];
size[x] = size[ls] + size[rs] + 1;
sum[x] = sum[ls] + sum[rs] + v[x];
mx[x] = gmax(mx[ls], mx[rs]);
cmax(mx[x], lmx[rs] + rmx[ls] + v[x]);
lmx[x] = gmax(lmx[ls], sum[ls] + v[x] + lmx[rs]);
rmx[x] = gmax(rmx[rs], sum[rs] + v[x] + rmx[ls]);
}
inline void pushdown(R int x)
{
R int ls = ch[x][0], rs = ch[x][1];
if (tag[x])
{
rev[x] = tag[x] = 0;
if (ls) tag[ls] = 1, v[ls] = v[x], sum[ls] = size[ls] * v[x];
if (rs) tag[rs] = 1, v[rs] = v[x], sum[rs] = size[rs] * v[x];
if (v[x]>= 0)
{
if (ls) lmx[ls] = rmx[ls] = mx[ls] = sum[ls];
if (rs) lmx[rs] = rmx[rs] = mx[rs] = sum[rs];
}
else
{
if (ls) lmx[ls] = rmx[ls] = 0, mx[ls] = v[x];
if (rs) lmx[rs] = rmx[rs] = 0, mx[rs] = v[x];
}
}
if (rev[x])
{
rev[x] ^= 1; rev[ls] ^= 1; rev[rs] ^= 1;
swap(lmx[ls], rmx[ls]);swap(lmx[rs], rmx[rs]);
swap(ch[ls][0], ch[ls][1]); swap(ch[rs][0], ch[rs][1]);
}
}
inline void rotate(R int x)
{
R int f = fa[x], gf = fa[f], d = ch[f][1] == x;
if (f == root) root = x;
(ch[f][d] = ch[x][d ^ 1]) > 0 ? fa[ch[f][d]] = f : 0;
(fa[x] = gf) > 0 ? ch[gf][ch[gf][1] == f] = x : 0;
fa[ch[x][d ^ 1] = f] = x;
update(f);
}
inline void splay(R int x, R int rt)
{
while (fa[x] != rt)
{
R int f = fa[x], gf = fa[f];
if (gf != rt) rotate((ch[gf][1] == f) ^ (ch[f][1] == x) ? x : f);
rotate(x);
}
update(x);
}
void build(R int l, R int r, R int rt)
{
if (l > r) return ;
R int mid = l + r >> 1, now = id[mid], last = id[rt];
if (l == r)
{
sum[now] = a[l];
size[now] = 1;
tag[now] = rev[now] = 0;
if (a[l] >= 0) lmx[now] = rmx[now] = mx[now] = a[l];
else lmx[now] = rmx[now] = 0, mx[now] = a[l];
}
else
{
build(l, mid - 1, mid);
build(mid + 1, r, mid);
}
v[now] = a[mid];
fa[now] = last;
update(now);
ch[last][mid >= rt] = now;
}
int find(R int x, R int rank)
{
if (tag[x] || rev[x]) pushdown(x);
R int ls = ch[x][0], rs = ch[x][1], lsize = size[ls];
if (lsize + 1 == rank) return x;
if (lsize >= rank)
return find(ls, rank);
else
return find(rs, rank - lsize - 1);
}
inline int prepare(R int l, R int tot)
{
R int x = find(root, l - 1), y = find(root, l + tot);
splay(x, 0);
splay(y, x);
return ch[y][0];
}
std::queue <int> q;
inline void Insert(R int left, R int tot)
{
for (R int i = 1; i <= tot; ++i ) a[i] = FastIn();
for (R int i = 1; i <= tot; ++i )
if (!q.empty()) id[i] = q.front(), q.pop();
else id[i] = ++cnt;
build(1, tot, 0);
R int z = id[(1 + tot) >> 1];
R int x = find(root, left), y = find(root, left + 1);
splay(x, 0);
splay(y, x);
fa[z] = y;
ch[y][0] = z;
update(y);
update(x);
}
void rec(R int x)
{
if (!x) return ;
R int ls = ch[x][0], rs = ch[x][1];
rec(ls); rec(rs); q.push(x);
fa[x] = ch[x][0] = ch[x][1] = 0;
tag[x] = rev[x] = 0;
}
inline void Delete(R int l, R int tot)
{
R int x = prepare(l, tot), f = fa[x];
rec(x); ch[f][0] = 0;
update(f); update(fa[f]);
}
inline void Makesame(R int l, R int tot, R int val)
{
R int x = prepare(l, tot), y = fa[x];
v[x] = val; tag[x] = 1; sum[x] = size[x] * val;
if (val >= 0) lmx[x] = rmx[x] = mx[x] = sum[x];
else lmx[x] = rmx[x] = 0, mx[x] = val;
update(y); update(fa[y]);
}
inline void Reverse(R int l, R int tot)
{
R int x = prepare(l, tot), y = fa[x];
if (!tag[x])
{
rev[x] ^= 1;
swap(ch[x][0], ch[x][1]);
swap(lmx[x], rmx[x]);
update(y); update(fa[y]);
}
}
inline void Query(R int l, R int tot)
{
R int x = prepare(l, tot);
printf("%d\n",sum[x] );
}
#define inf ((1 << 30))
int main()
{
R int n = FastIn(), m = FastIn(), l, tot, val;
R char op, op2;
mx[0] = a[1] = a[n + 2] = -inf;
for (R int i = 2; i <= n + 1; i++ )
{
a[i] = FastIn();
}
for (R int i = 1; i <= n + 2; ++i) id[i] = i;
n += 2; cnt = n; root = (n + 1) >> 1;
build(1, n, 0);
for (R int i = 1; i <= m; i++ )
{
op = getc();
while (op < 'A' || op > 'Z') op = getc();
getc(); op2 = getc();getc();getc();getc();getc();
if (op == 'M' && op2 == 'X')
{
printf("%d\n",mx[root] );
}
else
{
l = FastIn() + 1; tot = FastIn();
if (op == 'I') Insert(l, tot);
if (op == 'D') Delete(l, tot);
if (op == 'M') val = FastIn(), Makesame(l, tot, val);
if (op == 'R')
Reverse(l, tot);
if (op == 'G')
Query(l, tot);
}
}
return 0;
}
/*
9 14
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
GET-SUM 8 4
MAX-SUM
DELETE 12 1
GET-SUM 8 4
MAX-SUM
MAKE-SAME 3 3 2
GET-SUM 5 4
MAX-SUM
REVERSE 3 6
GET-SUM 5 4
MAX-SUM
*/

浙公网安备 33010602011771号