您的位置:首页 > 其它

【BZOJ1500】【NOI2005】维修数列

2018-01-15 09:24 344 查看
【题目链接】

点击打开链接

【思路要点】

使用Splay维护多个标记进行各种区间操作,代码实现较为困难。
内存限制64MB,注意内存回收,避免空间超限。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN 500005
#define MAXIN 4500005
struct Node {
int father, child[2];
int value, sum;
int size, all;
int left_max, right_max, mid_max;
bool rev, made_same;
} a[MAXN];
int available[MAXIN];
int size, root, total;
void clear(int x) {
a[x].father = 0;
a[x].child[0] = 0;
a[x].child[1] = 0;
a[x].value = 0;
a[x].sum = 0;
a[x].size = 0;
a[x].all = 0;
a[x].left_max = 0;
a[x].right_max = 0;
a[x].mid_max = 0;
a[x].rev = false;
a[x].made_same = false;
}
int get(int x) {
return a[a[x].father].child[1] == x;
}
void pushdown(int x) {
if (x == 0) return;
if (a[x].made_same) {
a[x].value = a[x].all;
a[x].sum = a[x].all * a[x].size;
if (a[x].all >= 0) {
a[x].left_max = a[x].sum;
a[x].right_max = a[x].sum;
a[x].mid_max = a[x].sum;
} else {
a[x].left_max = a[x].all;
a[x].right_max = a[x].all;
a[x].mid_max = a[x].all;
}
if (a[x].child[0]) {
a[a[x].child[0]].all = a[x].all;
a[a[x].child[0]].made_same = true;
}
if (a[x].child[1]) {
a[a[x].child[1]].all = a[x].all;
a[a[x].child[1]].made_same = true;
}
a[x].made_same = false;
a[x].all = 0;
}
if (a[x].rev) {
swap(a[x].left_max, a[x].right_max);
swap(a[x].child[0], a[x].child[1]);
if (a[x].child[0]) a[a[x].child[0]].rev ^= true;
if (a[x].child[1]) a[a[x].child[1]].rev ^= true;
a[x].rev = false;
}
}
void update(int x) {
if (x == 0) return;
a[x].size = 1;
a[x].sum = a[x].value;
a[x].left_max = a[x].value;
a[x].right_max = a[x].value;
a[x].mid_max = a[x].value;
if (a[x].child[0]) {
int tmp = a[x].child[0];
pushdown(tmp);
a[x].size += a[tmp].size;
a[x].mid_max = max(max(a[x].mid_max, a[tmp].mid_max), a[x].left_max + a[tmp].right_max);
a[x].left_max = max(a[tmp].left_max, a[x].left_max + a[tmp].sum);
a[x].right_max = max(a[x].right_max, a[x].sum + a[tmp].right_max);
a[x].sum += a[tmp].sum;
}
if (a[x].child[1]) {
int tmp = a[x].child[1];
pushdown(tmp);
a[x].size += a[tmp].size;
a[x].mid_max = max(max(a[x].mid_max, a[tmp].mid_max), a[x].right_max + a[tmp].left_max);
a[x].left_max = max(a[x].left_max, a[tmp].left_max + a[x].sum);
a[x].right_max = max(a[tmp].right_max, a[tmp].sum + a[x].right_max);
a[x].sum += a[tmp].sum;
}
}
void rotate(int x) {
pushdown(a[x].father);
pushdown(x);
int father = a[x].father, grand = a[father].father, tmp = get(x);
a[father].child[tmp] = a[x].child[tmp ^ 1];
a[a[x].child[tmp ^ 1]].father = father;
a[x].child[tmp ^ 1] = father;
a[father].father = x;
a[x].father = grand;
if (grand) a[grand].child[a[grand].child[1] == father] = x;
update(father);
update(x);
}
void splay(int x) {
for (int father = a[x].father; (father = a[x].father); rotate(x))
if (a[father].father) {
update(x);
rotate(get(x) == get(father) ? father : x);
}
root = x;
}
void splayII(int y, int x) {
for (int father = a[y].father; (father = a[y].father) != x; rotate(y))
if (a[father].father != x) {
update(y);
rotate(get(y) == get(father) ? father : y);
}
}
void init_splay() {
for (int i = 1; i < MAXN; i++) available[i] = i;
total = MAXN - 1; size = 2; root = 1;
a[1].child[1] = 2;
a[1].size = 2;
a[2].father = 1;
a[2].size = 1;
}
int findx(int x) {
int now = root;
while (true) {
pushdown(now);
if (x <= a[a[now].child[0]].size) now = a[now].child[0];
else {
x -= a[a[now].child[0]].size;
if (x == 1) {splay(now); return a[now].value; };
x--;
now = a[now].child[1];
}
}
}
int find_rank(int x) {
int now = root;
while (true) {
pushdown(now);
if (x <= a[a[now].child[0]].size) now = a[now].child[0];
else {
x -= a[a[now].child[0]].size;
if (x == 1) return now;
x--;
now = a[now].child[1];
}
}
}
int pre() {
int now = a[root].child[0];
pushdown(now);
while (a[now].child[1]) {
now = a[now].child[1];
pushdown(now);
}
return now;
}
void insert(int pos, int sum) {
findx(pos + 1);
int father = pre();
for (int i = 1; i <= sum; i++) {
int x;
scanf("%d", &x);
size++;
a[available[size]].father = father;
a[available[size]].value = x;
a[father].child[1] = available[size];
father = available[size];
}
splay(available[size]);
}
void get_interval(int x, int y) {
splay(x);
splayII(y, x);
}
void restore(int x) {
if (x == 0) return;
available[++total] = x;
restore(a[x].child[0]);
restore(a[x].child[1]);
clear(x);
}
void del(int pos, int n) {
int x = find_rank(pos), y = find_rank(pos + n + 1);
get_interval(x, y);
restore(a[y].child[0]);
a[y].child[0] = 0;
update(y);
update(x);
}
void make_same(int pos, int n, int v) {
int x = find_rank(pos), y = find_rank(pos + n + 1);
get_interval(x, y);
a[a[y].child[0]].all = v;
a[a[y].child[0]].made_same = true;
pushdown(a[y].child[0]);
update(y);
update(x);
}
void reverse(int pos, int n) {
int x = find_rank(pos), y = find_rank(pos + n + 1);
get_interval(x, y);
a[a[y].child[0]].rev ^= true;
pushdown(a[y].child[0]);
update(y);
update(x);
}
int get_sum(int pos, int n) {
int x = find_rank(pos), y = find_rank(pos + n + 1);
get_interval(x, y);
return a[a[y].child[0]].sum;
}
int max_sum(int pos, int n) {
int x = find_rank(pos), y = find_rank(pos + n + 1);
get_interval(x, y);
return a[a[y].child[0]].mid_max;
}
void print(int x) {
if (x == 0) return;
pushdown(x);
print(a[x].child[0]);
printf("%d\n", a[x].value);
print(a[x].child[1]);
}
int main() {
int n, m, pos, x;
scanf("%d%d", &n, &m);
init_splay();
insert(1, n);
int now = n;
char opt[15];
for (int i = 1; i <= m; i++) {
scanf("\n%s", opt);
if (opt[0] == 'I' && opt[1] == 'N') {
scanf("%d%d", &pos, &n);
insert(pos + 1, n);
now += n;
}
if (opt[0] == 'D' && opt[1] == 'E') {
scanf("%d%d", &pos, &n);
if (n > now - pos + 1) n = now - pos + 1;
del(pos, n);
now -= n;
}
if (opt[0] == 'M' && opt[2] == 'K') {
scanf("%d%d%d", &pos, &n, &x);
if (n > now - pos + 1) n = now - pos + 1;
make_same(pos, n, x);
}
if (opt[0] == 'R' && opt[1] == 'E') {
scanf("%d%d", &pos, &n);
if (n > now - pos + 1) n = now - pos + 1;
reverse(pos, n);
}
if (opt[0] == 'G' && opt[1] == 'E') {
scanf("%d%d", &pos, &n);
if (n > now - pos + 1) n = now - pos + 1;
printf("%d\n",get_sum(pos,n));
}
if (opt[0] == 'M' && opt[2] == 'X') {
printf("%d\n", max_sum(1, now));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: