CF1889C2 Doremy's Drying Plan (Hard Version) 题解
Description
有
Solution
一道比较好玩的 dp 题。建议评级紫。
单独考虑每个点。设现在在考虑点
如果我们按顺序考虑每个点是否不被覆盖,即在
考虑
上面的分析中已经分析出了子问题结构,考虑 dp。设
这个方程直接转移是
首先如果覆盖在
容易发现当
假设有
这个序列将
动态 st 表可以做到
最后问题只剩下如何对于每个
利用差分思想。对每个位置维护两个集合
维护完
维护完
Code
#include <iostream> #include <fstream> #include <algorithm> #include <vector> #include <set> #include <cstring> using namespace std; const int inf = 0x3f3f3f3f; namespace SparseTable { // bool bst; int st[11][18][200005]; // bool bed; int lg[200005]; int Init() { lg[0] = -1; for (int i = 1; i <= 200000; i ++) lg[i] = lg[i >> 1] + 1; return 0; } struct Table { int tot = 0, z; int clear() { tot = 0, z = 0; return 0; } int insert(int x) { tot ++; st[z][0][tot] = x; int u = tot; for (int i = 1; u - (1 << i) >= 0; i ++) st[z][i][u] = (max(st[z][i - 1][u], st[z][i - 1][u - (1 << (i - 1))])); return 0; } int query(int l, int r) { l ++, r ++; if (l > r) return -inf; int len = lg[r - l + 1]; return max(st[z][len][r], st[z][len][l + (1 << len) - 1]); } }; } namespace solve1 { struct Node { int a; Node(int x) { a = x; } }; bool operator<(Node a, Node b) { return a.a > b.a; } int n, m, k; using namespace SparseTable; Table st[11]; pair<int, int> a[200005]; #define l(u) a[u].first #define r(u) a[u].second set<int> add[200005], del[200005]; set<Node> cover; vector<int> cov[200005]; bool vis[200005]; int f[200005][11]; int clear() { for (int i = 0; i <= 10; i ++) st[i].clear(), st[i].z = i; for (int i = 1; i <= n + 1; i ++) cov[i].clear(), vis[i] = 0; return 0; } int main() { clear(); cin >> n >> m >> k; for (int i = 1; i <= m; i ++) cin >> l(i) >> r(i); sort(a + 1, a + m + 1); for (int i = 1; i <= m; i ++) add[l(i)].insert(i), del[r(i) + 1].insert(i); for (int i = 1; i <= n + 1; i ++) { cov[i].push_back(i); for (int j : del[i]) cover.erase(Node(j)); for (int j : add[i]) cover.insert(Node(j)); add[i].clear(), del[i].clear(); if (int(cover.size()) > k) vis[i] = 1; int cnt = 0; if (!vis[i] && (cover.size())) for (Node j : cover) { if (cnt == k) break; cov[i].push_back(l(j.a)), cnt ++; } } for (int i = 0; i <= k; i ++) st[i].insert(0); int ret = 0; for (int i = 1; i <= n; i ++) { if (vis[i]) { for (int j = 0; j <= k; j ++) st[j].insert(-inf), f[i][j] = -inf; continue; } int tt = cov[i].size(); for (int j = 0; j < tt - 1; j ++) f[i][j] = -inf; for (int j = tt - 1; j <= k; j ++) { f[i][j] = 0; for (int p = 0; p < tt; p ++) { if (p > j) break; if (p != tt - 1) f[i][j] = max(f[i][j], st[j - p].query(cov[i][p + 1], cov[i][p] - 1) + 1); else f[i][j] = max(f[i][j], st[j - p].query(0, cov[i][p] - 1) + 1); } } for (int j = 0; j <= k; j ++) st[j].insert(f[i][j]), ret = max(ret, f[i][j])/*, cout << i << " " << j << " " << f[i][j] << "\n"*/; } cout << ret << "\n"; return 0; } } signed main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); int T = 1; cin >> T; SparseTable::Init(); while (T --) solve1::main(); return 0; }
本文作者:AzusidNya
本文链接:https://www.cnblogs.com/AzusidNya/p/17803979.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步