2024杭电多校第8场
8#
1005 cats 的二分答案 (hdu7521)#
又是来自队友的思路,orz
设 \(x = r - l + 1\),由于二分操作最多进行 \(\log x\) 次,\(k\geq \log x\) 时不可能出现程序崩溃情况,由此可将需要讨论的 \(k\) 范围缩减至 \(60\) 以下。每次二分所产生新的子区间最多有两种不同情况,则总共存在不超过 \(2\log x\) 种区间,因此可将区间长度当作状态处理。设 \(f[i][j]\) 表示长度为 \(i\) 的区间、当前已有 \(j\) 次下标越界的情况总数,记忆化搜索求解。复杂度 \(\log^2 x\),可能还带一点unordered_map的常数,题解的dp常数小些,但写着不太顺手
记忆化搜索代码:
unordered_map <ll, ll> mp[61]; void dfs(ll x) { if(x <= 0) return; mp[0][x] = 1; // 二分恰好找到答案,下标不越界,也不需要继续dfs ll mid = (x + 1) / 2; if(!mp[0][mid - 1]) dfs(mid - 1); for(int i = 1; i <= k; i++) { mp[i][x] += mp[i - 1][mid - 1]; // 向前半段区间寻找,说明下标已越界 } if(!mp[0][x - mid]) dfs(x - mid); for(int i = 0; i <= k; i++) { mp[i][x] += mp[i][x - mid]; // 下标未越界 } }
1006 cats的最小生成树 (hdu7522)#
对于总共 \(m\) 条边而言,有效操作次数不会超过 \(k = \lfloor m/(n - 1)\rfloor\) 次,每次对 \(n\) 个点做最小生成树,考虑用 \(k\) 个并查集维护每次操作过程中图的连通性,整体空间复杂度 \(O(m)\). 连边操作时,二分查找左右端点不连通的最早时刻,极端情况下时间复杂度 \(m\log m\). 最后对每个并查集检查连通性,若第 \(i\) 次操作时图已经无法连通,则大于该操作次数的边都不会被加入生成树,输出-1.
int lev = m / (n - 1); // 即题解中的k if(lev == 0) { for(int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); printf("-1 "); } printf("\n"); return; // 按我的代码不特判就会re() } for(int i = 1; i <= lev; i++) { for(int j = 0; j <= n + 1; j++) { f[i].push_back(j); } } for(int i = 1; i <= m; i++) { int x, y, l = 1, r = lev; scanf("%d%d", &x, &y); ans[i] = lev + 1; if(find(lev, x) == find(lev, y)) continue; while(l <= r) { int mid = (l + r) / 2; if(find(mid, x) != find(mid, y)) { ans[i] = mid; r = mid - 1; } else l = mid + 1; } f[ans[i]][find(ans[i], x)] = find(ans[i], y); } int flag = lev + 1; for(int i = 1; i <= lev; i++) { int cnt = 0; for(int j = 1; j <= n; j++) { if(f[i][j] == j) cnt++; } if(cnt > 1) { flag = i; break; } } for(int i = 1; i <= m; i++) { if(ans[i] >= flag) printf("-1 "); else printf("%d ", ans[i]); }
1012 cats 的电脑中毒 (hdu7528)#
非常好题目,正解就是贪心的题还能想假也是离谱()将两个字符串不同字符的位置数量看作它们的“距离”,题意即转化为:求一个字符串 \(x\),其与三个给定字符串距离的最小值最大。嗯,看上去有点像二分或者dp,但经过我和wyq的尝逝,这两种思路都不对。
对于给定字符串 \(a,b,c\) 的第 \(i\) 位,若 \(a[i] = b[i] = c[i]\),\(x[i] \neq a[i]\) 显然是最优的,统计三个字符串相等的情况次数 \(s\);若 \(a[i] = b[i] \neq c[i]\),可暂时令 \(x[i] = c[i]\). 统计每个字符串与另外两者不等的次数,记作 \(cnt_a,cnt_b,cnt_c\). 此时 \(d_{ax} = s + cnt_b + cnt_c,\space d_{bx} = s + cnt_a + cnt_c, \space d_{cx} = s + cnt_a + cnt_b\),假设 \(cnt_a \leq cnt_b\leq cnt_c\),对于当前最小距离 \(d_{cx}\) 而言,适当调整 \(a[i] = b[i] \neq c[i]\) 情况下的取值、即令部分 \(x[i] = a[i],\space min(d_{ax} - k, d_{bx} - k, d_{cx} + k) = d_{cx} + k\) 显然更佳;该调整操作最多对一个字符串进行,若调整两个字符串的取值,使这两个字符串距离不变、另一字符串距离减小,答案不会更优。调整应当使 \(d_{cx}'\) 与较小的 \(d_{bx}'\) 尽可能接近,即有最终答案 \(d = s + cnt_a + (cnt_b + cnt_c) / 2\).
作者:Aderose_yr
出处:https://www.cnblogs.com/meowqwq/p/18359577
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
喵喵喵)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!