JOISC 2022 D3T3 蚂蚁与方糖

洛谷传送门

LOJ 传送门

UOJ 传送门

神题。

考虑如何计算二分图最大匹配。考虑利用扩展 Hall 定理,即 |A|maxSA{|S||N(S)|}。回到原题就是 sumredmax{[li,ri]}两两不交i=1ksumred(li,ri)sumblue(liL,ri+L)

注意到 {[li,ri]} 之间距离一定 >2L,否则合并一定更优。

考虑用前缀和简化式子。设 Ri,Bi 分别为红 / 蓝点个数前缀和,设 pi=Ri1+BiL1,qi=RiBi+L,等价于交替选 p,q 的最大权值和。

容易线段树上维护 fi,0/1,0/1 表示开始选了 p/q,结尾选了 p/q 的最大权值和。

然后考虑修改:

  • 添加红点,相当于 p[x+1,+)yq[x,)y。相当于 p,q[x+1,)pyqyq[x,x]y。前者只会影响 fi,0,0,fi,1,1

  • 添加蓝点,相当于 p[x+L+1,)yq[xL,)y。对于共同加减的区间可以像上面一样搞。对于 q[xL,x+L+1) 的区间加,因为相邻两个 q 的距离一定大于 2L,所以这段区间最多只选了一个 q。对于 fi,0/1,1 加上 y 即可。

时间复杂度 O(qlogq)

code
// Problem: P9528 [JOISC 2022 Day3] 蚂蚁与方糖
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P9528
// Memory Limit: 1 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;
const int maxn = 500100;
ll n, m, tot, lsh[maxn], f[maxn << 2][2][2], tag1[maxn << 2], tag2[maxn << 2];
struct node {
ll op, x, y;
} a[maxn];
inline void pushup(int x) {
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 2; ++j) {
f[x][i][j] = max(f[x << 1][i][j], f[x << 1 | 1][i][j]);
for (int k = 0; k < 2; ++k) {
f[x][i][j] = max(f[x][i][j], f[x << 1][i][k] + f[x << 1 | 1][k ^ 1][j]);
}
}
}
}
inline void pushtag1(int x, ll y) {
f[x][0][0] += y;
f[x][1][1] -= y;
tag1[x] += y;
}
inline void pushtag2(int x, ll y) {
f[x][0][1] += y;
f[x][1][1] += y;
tag2[x] += y;
}
inline void pushdown(int x) {
if (tag1[x]) {
pushtag1(x << 1, tag1[x]);
pushtag1(x << 1 | 1, tag1[x]);
tag1[x] = 0;
}
if (tag2[x]) {
pushtag2(x << 1, tag2[x]);
pushtag2(x << 1 | 1, tag2[x]);
tag2[x] = 0;
}
}
void update1(int rt, int l, int r, int ql, int qr, ll x) {
if (ql > qr) {
return;
}
if (ql <= l && r <= qr) {
pushtag1(rt, x);
return;
}
pushdown(rt);
int mid = (l + r) >> 1;
if (ql <= mid) {
update1(rt << 1, l, mid, ql, qr, x);
}
if (qr > mid) {
update1(rt << 1 | 1, mid + 1, r, ql, qr, x);
}
pushup(rt);
}
void update2(int rt, int l, int r, int ql, int qr, ll x) {
if (ql > qr) {
return;
}
if (ql <= l && r <= qr) {
pushtag2(rt, x);
return;
}
pushdown(rt);
int mid = (l + r) >> 1;
if (ql <= mid) {
update2(rt << 1, l, mid, ql, qr, x);
}
if (qr > mid) {
update2(rt << 1 | 1, mid + 1, r, ql, qr, x);
}
pushup(rt);
}
inline int ID(ll x) {
return lower_bound(lsh + 1, lsh + tot + 1, x) - lsh;
}
void solve() {
scanf("%lld%lld", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf("%lld%lld%lld", &a[i].op, &a[i].x, &a[i].y);
lsh[++tot] = a[i].x;
}
sort(lsh + 1, lsh + tot + 1);
tot = unique(lsh + 1, lsh + tot + 1) - lsh - 1;
ll s = 0;
for (int i = 1; i <= n; ++i) {
ll op = a[i].op, x = a[i].x, y = a[i].y;
if (op == 1) {
s += y;
update1(1, 0, tot, ID(x + 1), tot, -y);
update2(1, 0, tot, ID(x), ID(x), y);
} else {
update1(1, 0, tot, ID(x + m + 1), tot, y);
update2(1, 0, tot, ID(x - m), ID(x + m + 1) - 1, -y);
}
printf("%lld\n", s - f[1][0][1]);
}
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}
posted @   zltzlt  阅读(72)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示