JOISC 2022 D3T3 蚂蚁与方糖
神题。
考虑如何计算二分图最大匹配。考虑利用扩展 Hall 定理,即 。回到原题就是 。
注意到 之间距离一定 ,否则合并一定更优。
考虑用前缀和简化式子。设 分别为红 / 蓝点个数前缀和,设 ,等价于交替选 的最大权值和。
容易线段树上维护 表示开始选了 ,结尾选了 的最大权值和。
然后考虑修改:
-
添加红点,相当于 在 减 , 在 加 。相当于 在 中 减 , 加 。 在 加 。前者只会影响 。
-
添加蓝点,相当于 在 加 , 在 加 。对于共同加减的区间可以像上面一样搞。对于 在 的区间加,因为相邻两个 的距离一定大于 ,所以这段区间最多只选了一个 。对于 加上 即可。
时间复杂度 。
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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App