Description
JOI 君是一个生物学家。他准备对蚂蚁和方糖做一些实验。
JOI 君的实验在一个长度为 109 的木条上进行。这根木条被从左往右放置。木条上距离左端点 x 的点被称作坐标为 x 的点。
现在,木条上什么都没有。JOI 君将会进行 Q 次操作。第 i 个操作 (1≤i≤Q) 由三个整数 Ti,Xi,Ai 描述,表示:
- 若 Ti=1,JOI 君在坐标为 Xi 的点处放了 Ai 个蚂蚁。
- 若 Ti=2,JOI 君在坐标为 Xi 的点处放了 Ai 块方糖。
由于蚂蚁和方糖都很小,所以可能会有一些蚂蚁和方糖放在同一个点上。JOI 君也可能在同一个点执行多次操作。
这次实验中使用的蚂蚁具有「好奇心强」的萌点。具体地,当 JOI 君拍手时,每个蚂蚁会执行以下操作:
- 如果存在一块方糖与该蚂蚁距离不超过 L,它会选择任意一块并吃掉。
可能存在多个蚂蚁同时吃掉一块方糖的情况。
对于每个 k (1≤k≤Q),JOI 君想要知道以下问题的答案。
- 假设 JOI 君在第 k 次操作后拍了一次手,最多有多少块方糖被至少一个蚂蚁吃掉了?
请写一个程序,对于给定的 JOI 君执行的操作和 L 的值,对于所有 k 回答 JOI 君的每个问题。
注意 JOI 君并不会真的拍手。因此蚂蚁的位置不会改变,方糖也不会被吃掉。
对于所有数据,满足:
- 1≤Q≤500000。
- 1≤L≤109。
- Ti∈{1,2}。
- 0≤Xi≤109 (1≤i≤Q)。
- 1≤Ai≤109 (1≤i≤Q)。
Solution
首先可以转化为二分图最大匹配问题,即对于位置在 x 的蚂蚁,向 [x−L,x+R] 内的方糖连边,问最大匹配。
跑网络流显然是不行的。这时就要用到 Hall 定理:设左部点集合为 A,右部点集合为 B,则最大匹配为 ∣A∣−S⊆Amax{∣S∣−∣Nb(S)∣}。
注意到这里的每个左部点连接的是个长度相等的区间,所以用 Hall 定理会很好做。
具体的,选择的左部点集合一定构成若干个区间 [l1,r1],[l2,r2],…,[lk,rk],对应的右部点集合为 [l1−L,r1+L],[l2−L,r2+L],…,[lk−L,rk+L]。
容易发现如果存在 [li,ri] 和 [lj,rj] 有交或者 [li−L,ri+L] 和 [lj−L,rj+L] 有交,那么将其合并一定更优。
所以最终的区间一定满足 li−ri−1>2L。
设 pi=cntant1,i−cntsugar1,i+L,qi=cntant1,i−1−cntsugar1,i−1−L,则一个区间 [l,r] 的贡献为 pr−ql。
现在问题转化为了选择 k 个区间,要求最大化 ∑i=1k(pri−qli)。单次询问可以 dp 做。
考虑用线段树维护上面的那个 dp,设 fx,0/1,0/1 表示 x 对应的区间,选的第一个为 l 还是 r,最后一个是 l 还是 r。
如果在 x 处加入 c 个蚂蚁,那么变化为:[x,+∞] 的 pi 加 ci,[x+1,+∞] 的 qi 加 ci。转换一下,变为 px 加 ci,[x+1,+∞] 的 pi 和 qi 同时加 ci。
前面的是单点修改,后面的 4 种 dp 最优选法一定不变,打个标记即可。
如果在 x 处加入 c 块方糖,变化为:[x−L,x+L] 的 pi 加 −ci,[x+L+1,+∞] 的 pi 和 qi 同时加 −ci。
后面的和上面是一样的。由于最优方案一定满足 ri−li−1>2L,所以 [x−L,x+R] 内部的四种 dp 的最优方案选的点数也是确定的,同样打标记即可。
具体见代码。
时间复杂度:O(QlogQ)。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| #include <bits/stdc++.h>
#define int int64_t
using pii = std::pair<int, int>;
const int kMaxN = 5e5 + 5;
int n, m, L; int op[kMaxN], x[kMaxN], c[kMaxN], unq[kMaxN];
struct Node { int LL, LR, RL, RR; friend Node operator +(const Node &n1, const Node n2) { static Node ret; ret.LL = std::max({n1.LL, n2.LL, n1.LL + n2.RL, n1.LR + n2.LL}); ret.LR = std::max({n1.LR, n2.LR, n1.LL + n2.RR, n1.LR + n2.LR}); ret.RL = std::max({n1.RL, n2.RL, n1.RL + n2.RL, n1.RR + n2.LL}); ret.RR = std::max({n1.RR, n2.RR, n1.RL + n2.RR, n1.RR + n2.LR}); return ret; } };
struct SGT { Node t[kMaxN * 4]; std::array<int, 4> tag[kMaxN * 4]; void pushup(int x) { t[x] = t[x << 1] + t[x << 1 | 1]; } void addtag(int x, std::array<int, 4> v) { t[x].LL += v[0], t[x].LR += v[1], t[x].RL += v[2], t[x].RR += v[3]; tag[x][0] += v[0], tag[x][1] += v[1], tag[x][2] += v[2], tag[x][3] += v[3]; } void pushdown(int x) { if (tag[x][0] || tag[x][1] || tag[x][2] || tag[x][3]) { addtag(x << 1, tag[x]), addtag(x << 1 | 1, tag[x]); tag[x] = {0, 0, 0, 0}; } } void update(int x, int l, int r, int ql, int qr, std::array<int, 4> v) { if (l > qr || r < ql) return; else if (l >= ql && r <= qr) return addtag(x, v); pushdown(x); int mid = (l + r) >> 1; update(x << 1, l, mid, ql, qr, v), update(x << 1 | 1, mid + 1, r, ql, qr, v); pushup(x); } } sgt;
int getid(int x) { return std::lower_bound(unq + 1, unq + 1 + m, x) - unq; }
void discrete() { std::sort(unq + 1, unq + 1 + m); m = std::unique(unq + 1, unq + 1 + m) - (unq + 1); }
void dickdreamer() { std::cin >> n >> L; for (int i = 1; i <= n; ++i) { std::cin >> op[i] >> x[i] >> c[i]; unq[++m] = x[i]; } discrete(); int tot = 0; for (int i = 1; i <= n; ++i) { if (op[i] == 1) { int id = getid(x[i]); sgt.update(1, 1, m, id, id, {0, c[i], 0, c[i]}); sgt.update(1, 1, m, id + 1, m, {-c[i], 0, 0, c[i]}); tot += c[i]; } else { int id1 = getid(x[i] - L), id2 = getid(x[i] + L + 1); sgt.update(1, 1, m, id1, id2 - 1, {0, -c[i], 0, -c[i]}); sgt.update(1, 1, m, id2, m, {c[i], 0, 0, -c[i]}); } std::cout << tot - std::max<int>(sgt.t[1].LR, 0) << '\n'; } }
int32_t main() { #ifdef ORZXKR freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0); int T = 1; while (T--) dickdreamer(); return 0; }
|