思路
很板的题,但是很有必要写。
对于最大子列和,用区间合并的思想求;
对于区间翻转,用平衡树反转的思想求;
对于插入区间,分裂后硬插即可,但注意不要裂成俩之后再调用原始的插入,因为裂开之后root变了,插入操作是错的。不如直接建一棵新的平衡树插点,然后在裂开合并三段即可。
注意下放标记的顺序。
好题!
**#include <bits/stdc++.h>
#pragma gcc optimize("O2")
#pragma g++ optimize("O2")
#define int long long
#define endl '\n'
using namespace std;
const int N = 5e5 + 10, INF = 1e9;
namespace FHQ {
struct Info {
int sum, pres, sufs, maxs;
inline void init(int x, int sz) {
sum = x * sz, pres = sufs = maxs = x < 0 ? x : sum;
}
inline void set(int x) { sum = pres = sufs = maxs = x; }
inline void clc() { sum = 0, pres = sufs = maxs = -INF; }
friend Info operator+ (Info a, Info b) {
return Info {
a.sum + b.sum,
max(a.pres, a.sum + b.pres),
max(b.sufs, b.sum + a.sufs),
max({a.maxs, b.maxs, a.sufs + b.pres})};
}
} tree[N];
struct stk {
int s[N], id;
stk(): id(0) {}
void push(int x) { s[++id] = x; }
int top() { return s[id]; }
void pop() { --id; }
bool empty() { return id == 0; }
} stk;
int lc[N], rc[N], key[N], siz[N], val[N], chg[N];;
bool lazy[N];
int tot, root;
std::mt19937 Rand(114514);
inline void make_node(int &rt, int x) {
if(!stk.empty()) {
rt = stk.top(), stk.pop();
tree[rt].set(x);
} else {
tree[rt = ++tot].set(x);
}
val[rt] = x, key[rt] = Rand(), siz[rt] = 1, chg[rt] = INF, lazy[rt] = false;
}
inline void push_up(int rt) {
siz[rt] = siz[lc[rt]] + siz[rc[rt]] + 1;
Info now; now.set(val[rt]);
tree[rt] = tree[lc[rt]] + now + tree[rc[rt]];
// cout << "# Merged Operation: " << "(" << lc[rt] << ", " << rc[rt] << "), sum => " << tree[rt].sum << endl;
}
inline void push_down(int rt) {
if(lazy[rt]) {
if(lc[rt]) lazy[lc[rt]] ^= 1, swap(tree[lc[rt]].pres, tree[lc[rt]].sufs);
if(rc[rt]) lazy[rc[rt]] ^= 1, swap(tree[rc[rt]].pres, tree[rc[rt]].sufs);
swap(lc[rt], rc[rt]);
lazy[rt] = false;
}
if(chg[rt] < INF) {
// cout << "# PushDown Change Tag: Root = " << rt << ", val = " << chg[rt] << endl;
if(lc[rt]) tree[lc[rt]].init(chg[rt], siz[lc[rt]]), val[lc[rt]] = chg[lc[rt]] = chg[rt];
if(rc[rt]) tree[rc[rt]].init(chg[rt], siz[rc[rt]]), val[rc[rt]] = chg[rc[rt]] = chg[rt];
chg[rt] = INF;
}
}
void split(int rt, int x, int &u, int &v) {
if(!rt) return u = v = 0, void();
push_down(rt);
if(x > siz[lc[rt]]) u = rt, split(rc[rt], x - siz[lc[rt]] - 1, rc[rt], v);
else v = rt, split(lc[rt], x, u, lc[rt]);
push_up(rt);
}
int merge(int u, int v) {
if(!u || !v) return u + v;
push_down(u), push_down(v);
if(key[u] > key[v]) {
rc[u] = merge(rc[u], v);
return push_up(u), u;
} else {
lc[v] = merge(u, lc[v]);
return push_up(v), v;
}
}
void insert(int x) {
int new_node; make_node(new_node, x);
root = merge(root, new_node);
}
void clc(int x) {
tree[x].clc(), val[x] = lc[x] = rc[x] = siz[x] = key[x] = lazy[x] = 0, chg[x] = INF;
stk.push(x);
}
void del(int x) {
if(!x) return;
del(lc[x]), del(rc[x]), clc(x);
}
}
using FHQ::root;
using FHQ::stk;
inline int get_opid(string op) {
if(op[0] == 'I') return 1;
else if(op[0] == 'D') return 2;
else if(op[0] == 'M' && op[2] == 'K') return 3;
else if(op[0] == 'R') return 4;
else if(op[0] == 'G') return 5;
else if(op[0] == 'M' && op[2] == 'X') return 6;
return 0;
}
inline void solve() {
FHQ::tree[0].clc();
int n, m; cin >> n >> m;
for(int i = 1; i <= n; i++) {
int x; cin >> x;
FHQ::insert(x);
}
for(int c = 1; c <= m; c++) {
string op; cin >> op;
int ops = get_opid(op);
if(ops == 1) {
int posi, tot; cin >> posi >> tot;
int nrt = 0;
for(int i = 1; i <= tot; i++) {
int v = 0; cin >> v;
int nd; FHQ::make_node(nd, v);
nrt = FHQ::merge(nrt, nd);
}
int spl, spr;
FHQ::split(root, posi, spl, spr);
root = FHQ::merge(FHQ::merge(spl, nrt), spr);
} else if(ops == 2) {
int posi, tot; cin >> posi >> tot;
int spl, spm, spr;
FHQ::split(root, posi + tot - 1, spl, spr);
FHQ::split(spl, posi - 1, spl, spm);
FHQ::del(spm);
root = FHQ::merge(spl, spr);
} else if(ops == 3) {
int posi, tot, chg; cin >> posi >> tot >> chg;
int spl, spm, spr;
FHQ::split(root, posi + tot - 1, spl, spr);
FHQ::split(spl, posi - 1, spl, spm);
FHQ::chg[spm] = FHQ::val[spm] = chg, FHQ::tree[spm].init(chg, FHQ::siz[spm]);
root = FHQ::merge(FHQ::merge(spl, spm), spr);
// cout << "Test MID trans >>> " ;
// FHQ::print_mid(root); cout << endl;
// cout << "Test MID tags >>> " ;
// FHQ::print_mid_chg(root); cout << endl;
} else if(ops == 4) {
int posi, tot; cin >> posi >> tot;
int spl, spm, spr;
FHQ::split(root, posi + tot - 1, spl, spr);
FHQ::split(spl, posi - 1, spl, spm);
FHQ::lazy[spm] ^= 1;
root = FHQ::merge(FHQ::merge(spl, spm), spr);
} else if(ops == 5) {
int posi, tot; cin >> posi >> tot;
int spl, spm, spr;
FHQ::split(root, posi + tot - 1, spl, spr);
FHQ::split(spl, posi - 1, spl, spm);
cout << FHQ::tree[spm].sum << endl;
root = FHQ::merge(FHQ::merge(spl, spm), spr);
} else if(ops == 6) {
cout << FHQ::tree[root].maxs << endl;
}
}
}
signed main() {
ios_base::sync_with_stdio(false), cin.tie(0);
int t = 1; // cin >> t;
while(t--) solve();
return 0;
}**
656

被折叠的 条评论
为什么被折叠?



