建议投稿到休闲娱乐
Register_int · · 题解
大家好啊,看着题解区千篇一律的简洁做法是不是感觉有点枯燥了?我来提供一个锤子做法给大家乐一乐。
静态的问题显然就是反悔贪心。我们从右往左贪,能拿就拿,如果拿了会让左括号太多,就把之前最小的那个左括号扔掉。
现在这个东西要带修,看上去形式并不是很好,所以先对要维护的元素做一个简化。不妨枚举一个
于是转化为这个问题:维护
- 给定
x 并选择头尾一段,将前x 个序列推入一个-1 ,后V-x 个推入一个1 。 - 设第
i 个序列对应的值域段长度为w_i ,所有后缀和的最大值为x_i ,求\sum_i w_i\lceil x/2\rceil 。
维护每个序列的最大后缀和
总时间复杂度同样为
:::info[Code]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 4e5 + 10;
const int MAXM = 8e5 + 10;
int b[MAXM], m;
struct node {
ll x, s; int ox, os;
int lx, rx, ls, rs;
int tp, tx, ts;
} t[MAXM << 2];
void build(int l = 1, int r = m, int p = 1) {
auto &_ = t[p]; _.x = _.s = _.ox = _.os = 0;
_.lx = _.rx = _.ls = _.rs = _.tp = _.tx = _.ts = 0;
if (l == r) return ; int mid = l + r >> 1;
build(l, mid, p << 1), build(mid + 1, r, p << 1 | 1);
}
inline
void pushup(int p) {
auto &_ = t[p], &l = t[p << 1], &r = t[p << 1 | 1];
_.x = l.x + r.x, _.s = l.s + r.s;
_.ox = l.ox + r.ox, _.os = l.os + r.os;
_.lx = l.lx, _.rx = r.rx, _.ls = l.ls, _.rs = r.rs;
}
inline
void upd(int p, int l, int r, int dx, int ds) {
auto &_ = t[p]; int w = b[r] - b[l - 1];
_.x += (ll)dx * w, _.s += (ll)ds * w;
_.lx += dx, _.rx += dx, _.ls += ds, _.rs += ds;
if (dx & 1) _.ox = w - _.ox; if (ds & 1) _.os = w - _.os;
_.tp == 2 ? _.tx += dx - ds : _.tx += dx, _.ts += ds;
}
inline
void setval(int p, int l, int r, int x) {
auto &_ = t[p]; int w = b[r] - b[l - 1];
_.x = (ll)w * x, _.ox = x & 1 ? w : 0, _.lx = _.rx = x;
_.tp = 1, _.tx = x;
}
inline
void align(int p, int l, int r, int c) {
auto &_ = t[p]; int w = b[r] - b[l - 1];
_.x = _.s + (ll)c * w, _.ox = c & 1 ? w - _.os : _.os;
_.lx = _.ls + c, _.rx = _.rs + c;
_.tp = 2, _.tx = c;
}
inline
void pushdown(int p, int l, int r) {
auto &_ = t[p]; int mid = l + r >> 1;
if (!_.tp) {
upd(p << 1, l, mid, _.tx, _.ts);
upd(p << 1 | 1, mid + 1, r, _.tx, _.ts);
} else {
upd(p << 1, l, mid, 0, _.ts);
upd(p << 1 | 1, mid + 1, r, 0, _.ts);
if (_.tp == 1) {
setval(p << 1, l, mid, _.tx);
setval(p << 1 | 1, mid + 1, r, _.tx);
} else {
align(p << 1, l, mid, _.tx);
align(p << 1 | 1, mid + 1, r, _.tx);
}
}
_.tp = _.tx = _.ts = 0;
}
void add(int k, bool fl, int l = 1, int r = m, int p = 1) {
if (r <= k || l > k) {
int w = r <= k ? 1 : -1;
return upd(p, l, r, fl ? 0 : w, w);
}
int mid = l + r >> 1; pushdown(p, l, r);
add(k, fl, l, mid, p << 1), add(k, fl, mid + 1, r, p << 1 | 1), pushup(p);
}
void modify_l(int l = 1, int r = m, int p = 1) {
if (t[p].lx >= t[p].ls) return ;
if (t[p].rx <= t[p].rs) return align(p, l, r, 0);
int mid = l + r >> 1; pushdown(p, l, r);
modify_l(l, mid, p << 1), modify_l(mid + 1, r, p << 1 | 1), pushup(p);
}
void modify_r(int l = 1, int r = m, int p = 1) {
if (t[p].rx >= 0) return ;
if (t[p].lx < 0) return setval(p, l, r, 0);
int mid = l + r >> 1; pushdown(p, l, r);
modify_r(l, mid, p << 1), modify_r(mid + 1, r, p << 1 | 1), pushup(p);
}
inline
void insert(int k, int fl) {
k = lower_bound(b + 1, b + m + 1, k) - b;
add(k, fl), fl ? modify_l() : modify_r();
}
int T, n, op[MAXN], x[MAXN], y[MAXN];
int main() {
freopen("brackets.in", "r", stdin);
freopen("brackets.out", "w", stdout);
for (scanf("%d", &T); T--; ) {
scanf("%d", &n), m = 0;
for (int i = 1; i <= n; i++) scanf("%d%d%d", &op[i], &x[i], &y[i]);
for (int i = 1; i <= n; i++) b[++m] = x[i], b[++m] = y[i];
sort(b + 1, b + m + 1), m = unique(b + 1, b + m + 1) - b - 1;
b[0] = b[1], build(); ll sum = 0;
for (int i = 1; i <= n; i++) {
if (op[i] == 1) insert(x[i], 1), insert(y[i], 1);
else if (op[i] == 2) insert(x[i], 1), insert(y[i], 0);
else insert(x[i], 0), insert(y[i], 0); sum += x[i] + y[i];
printf("%lld\n", sum - (ll)b[1] * i - (t[1].x + t[1].ox >> 1));
}
}
}
:::