BZOJ 1500 维修数列
Splay序列操作的大模板题
这个真的是噩梦。。调了整整一个晚上,可以说完全被榨干了orz。。
因为我的splay写的实在是太丑了,手动加的哨兵节点,开头忘记pushup了,找了一晚上才找到。。。
还有就是0节点的mx也要设置成-INF,否则会影响我门原树叶子结点的mx。。其他的就靠造化了。。
还要注意的是数组500000就够了,剩下的靠内存池维护,不然在BZOJ上会爆内存,但是他显示的是TLE。。不仅题目坑,这个评测也挺不友好的。。但是在洛谷还是可以过的
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
int X = 0, w = 0; char ch = 0;
while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
return w ? -X : X;
}
inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
A ans = 1;
for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
return ans;
}
const int N = 500005;
int ch[N][2], sum[N], mx[N], lx[N], rx[N], lazy[N], rev[N], val[N], fa[N], size[N], a[N];
int tot, n, m, root;
queue<int> q;
int newNode(int p, int v){
if(!q.empty()){
int ret = q.front(); q.pop();
sum[ret] = v, mx[ret] = val[ret] = v;
if(v >= 0) lx[ret] = rx[ret] = v;
else lx[ret] = rx[ret] = 0;
lazy[ret] = rev[ret] = ch[ret][0] = ch[ret][1] = 0;
fa[ret] = p, size[ret] = 1;
return ret;
}
else{
sum[++tot] = v, mx[tot] = val[tot] = v;
if(v >= 0) lx[tot] = rx[tot] = v;
else lx[tot] = rx[tot] = 0;
lazy[tot] = rev[tot] = ch[tot][0] = ch[tot][1] = 0;
fa[tot] = p, size[tot] = 1;
return tot;
}
}
void recycle(int x){
if(!x) return;
recycle(ch[x][0]);
recycle(ch[x][1]);
q.push(x);
}
void push_up(int x){
int l = ch[x][0], r = ch[x][1];
sum[x] = sum[l] + sum[r] + val[x];
size[x] = size[l] + size[r] + 1;
lx[x] = max(lx[l], sum[l] + val[x] + lx[r]);
rx[x] = max(rx[r], sum[r] + val[x] + rx[l]);
mx[x] = max(mx[l], mx[r], rx[l] + val[x] + lx[r]);
}
void push_down(int x){
int l = ch[x][0], r = ch[x][1];
if(lazy[x]){
lazy[x] = rev[x] = 0;
if(l) sum[l] = val[x] * size[l], val[l] = val[x], lazy[l] = 1;
if(r) sum[r] = val[x] * size[r], val[r] = val[x], lazy[r] = 1;
if(val[x] >= 0){
if(l) lx[l] = rx[l] = mx[l] = sum[l];
if(r) lx[r] = rx[r] = mx[r] = sum[r];
}
else{
if(l) lx[l] = rx[l] = 0, mx[l] = val[x];
if(r) lx[r] = rx[r] = 0, mx[r] = val[x];
}
}
if(rev[x]){
rev[x] ^= 1, rev[l] ^= 1, rev[r] ^= 1;
swap(lx[l], rx[l]), swap(lx[r], rx[r]);
swap(ch[l][0], ch[l][1]), swap(ch[r][0], ch[r][1]);
}
}
void rotate(int x){
int y = fa[x], z = fa[y], p = (ch[y][1] == x) ^ 1;
push_down(y), push_down(x);
ch[y][p^1] = ch[x][p], fa[ch[x][p]] = y;
fa[x] = z, ch[z][ch[z][1] == y] = x, fa[y] = x, ch[x][p] = y;
push_up(y), push_up(x);
}
void splay(int x, int goal){
if(x == goal) return;
while(fa[x] != goal){
int y = fa[x], z = fa[y];
if(z != goal){
if((ch[y][0] == x) ^ (ch[z][0] == y)) rotate(x);
else rotate(y);
}
rotate(x);
}
push_up(x);
if(goal == 0) root = x;
}
int find(int k){
if(!root) return 0;
int cur = root, r = size[ch[cur][0]];
while(1){
push_down(cur);
if(r < k){
k -= r + 1;
cur = ch[cur][1];
}
else{
if(r > k) cur = ch[cur][0];
else return cur;
}
r = size[ch[cur][0]];
}
}
int buildTree(int p, int l, int r){
if(l > r) return 0;
int mid = (l + r) >> 1;
int cur = newNode(p, a[mid]);
ch[cur][0] = buildTree(cur, l, mid - 1);
ch[cur][1] = buildTree(cur, mid + 1, r);
push_up(cur);
return cur;
}
void insert(int pos, int k){
if(!k) return;
for(int i = 1; i <= k; i ++) a[i] = read();
int x = find(pos), y = find(pos + 1);
splay(x, 0), splay(y, root);
ch[y][0] = buildTree(y, 1, k);
push_up(y), push_up(x);
}
void erase(int pos, int k){
if(!k) return;
int x = find(pos - 1), y = find(pos + k);
splay(x, 0), splay(y, root);
recycle(ch[y][0]);
ch[y][0] = 0;
push_up(y), push_up(x);
}
void modify(int pos, int k, int c){
if(!k) return;
int x = find(pos - 1), y = find(pos + k);
splay(x, 0), splay(y, root);
int key = ch[y][0];
val[key] = c, sum[key] = size[key] * c, lazy[key] = 1;
if(val[key] >= 0) mx[key] = lx[key] = rx[key] = sum[key];
else mx[key] = c, lx[key] = rx[key] = 0;
push_up(y), push_up(x);
}
void reverse(int pos, int k){
if(!k) return;
int x = find(pos - 1), y = find(pos + k);
splay(x, 0), splay(y, root);
int key = ch[y][0];
if(!lazy[key]){
rev[key] ^= 1;
swap(lx[key], rx[key]), swap(ch[key][0], ch[key][1]);
push_up(y), push_up(x);
}
}
int getSum(int pos, int k){
if(!k) return 0;
int x = find(pos - 1), y = find(pos + k);
splay(x, 0), splay(y, root);
return sum[ch[y][0]];
}
int getMax(){
return mx[root];
}
int main(){
n = read(), m = read();
mx[0] = -INF;
root = newNode(0, -INF), ch[root][1] = newNode(root, -INF);
for(int i = 1; i <= n; i ++) a[i] = read();
ch[ch[root][1]][0] = buildTree(ch[root][1], 1, n);
push_up(ch[root][1]), push_up(root);
while(m --){
char opt[20]; scanf("%s", opt);
if(opt[2] == 'X') printf("%d\n", getMax());
else{
int pos = read(), tot = read();
if(opt[0] == 'I') insert(pos, tot);
else if(opt[0] == 'D') erase(pos, tot);
else if(opt[0] == 'M') { int c = read(); modify(pos, tot, c); }
else if(opt[0] == 'R') reverse(pos, tot);
else if(opt[0] == 'G') printf("%d\n", getSum(pos, tot));
}
}
return 0;
}