当前位置: 首页 > news >正文

20250921 模拟赛 T4 题解

Description

https://zhengruioi.com/problem/3343?cid=1976

Solution

容易发现区间 LIS 满足四边形不等式,所以最终的答案关于划分段数是凸的。

\(d_i=f_i-f_{i-1}\)。那么由于 \(\sum d_i=n\)\(d_i\) 不增,所以 \(d_i\) 只有 \(O(\sqrt n)\) 种取值。

于是就只需要求出 \(g_k\) 表示 \(d_i\geq k\) 的最大的 \(i\),这个 \(g_k\) 也只有 \(O(\sqrt n)\) 种取值。

求单点的 \(g_k\) 的做法是设一个区间的贡献是 LIS 减 \(k\),然后再对一个 pair 进行 dp,这个 pair 的含义是 {最大权值,最大段数}。

对于所有的 \(g_k\) 考虑分治求,假设现在需要求出 \([l,r]\)\(g_k\) 值,先暴力求出 \(g_{mid}\) 的值 \(v\),如果 \(v=g_{l-1}\) 就说明 \([l,mid-1]\) 全是 \(v\),直接赋值,否则继续递归。对于右区间同理。

可以证明只需要求 \(O(\sqrt n)\) 次单点 \(g_k\) 的值。

时间复杂度:\(O(n\sqrt n\log n)\)

Code

#include <bits/stdc++.h>// #define int int64_tusing pii = std::pair<int, int>;const int kMaxN = 1.5e5 + 5;int cid, n;
int a[kMaxN], d[kMaxN], res[kMaxN];
int ct;template<class T> inline void chkmax(T &x, T y) { x = (x > y ? x : y); }
template<class T> inline void chkmin(T &x, T y) { x = (x < y ? x : y); }struct BIT {pii c[kMaxN];void clear() { std::fill_n(c + 1, n + 1, pii{-1e9, 0}); }void upd(int x, pii v) {for (; x <= n + 1; x += x & -x) chkmax(c[x], v);}pii qry(int x) {pii ret = {-1e9, 0};for (; x; x -= x & -x) chkmax(ret, c[x]);return ret;}
} bit;int get(int k) {static pii f[kMaxN];bit.clear();bit.upd(n + 1, {0, 0});++ct;pii mx = {0, 0};for (int i = 1; i <= n; ++i) {pii v1 = mx, v2 = bit.qry(a[i] - 1);v1.first += 1 - k, ++v1.second, ++v2.first;bit.upd(a[i], f[i] = std::max(v1, v2));chkmax(mx, f[i]);}return bit.qry(n + 1).second;
}void solve(int l, int r, int vl, int vr) {if (l > r) return;int mid = (l + r) >> 1, val = get(mid);d[mid] = val;if (val == vl) {for (int i = l; i < mid; ++i) d[i] = val;} else {solve(l, mid - 1, vl, val);}if (val == vr) {for (int i = mid + 1; i <= r; ++i) d[i] = val;} else {solve(mid + 1, r, val, vr);}
}void dickdreamer() {std::cin >> n;for (int i = 1; i <= n; ++i) std::cin >> a[i];d[0] = n, d[n + 1] = 0;// std::cerr << get(1) << '\n';ct = 0;solve(1, n, n, 0);for (int i = n; ~i; --i) {for (int j = d[i + 1] + 1; j <= d[i]; ++j)res[j] = res[j - 1] + i;}for (int i = 1; i <= n; ++i) std::cout << res[i] << " \n"[i == n];// for (int i = 0; i <= n + 1; ++i) std::cerr << d[i] << " \n"[i == n + 1];
}int32_t main() {freopen("lis.in", "r", stdin);freopen("lis.out", "w", stdout);std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);int T = 1;std::cin >> cid >> T;while (T--) dickdreamer();// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";return 0;
}
http://www.rkmt.cn/news/9028.html

相关文章:

  • 1.3 课前问题列表
  • warm-flow 监听器对象获取问题
  • Hexo Butterfly 5.4 分页问题 YAML 错误 解决方法总结
  • 第十一届中国大学生程序设计竞赛网络预选赛(CCPC Online 2025)
  • 完整教程:数据结构 栈和队列、树
  • 酵母双杂交技术:高通量筛选的突破与不可忽视的三大局限性
  • ubuntu20.04测试cuda
  • Promise中处理请求超时问题
  • AI驱动建筑行业数字化转型
  • VSCode 把代码发送到激活状态下的终端
  • 线性结构之数组[基于郝斌课程]
  • 完整教程:Vue中的props方式
  • 完整教程:MySQL 存储过程完整实战手册---一篇吃透 Stored Procedure
  • 「MCOI-05」魔仙
  • BlueHat v18 会议资料现已发布:前沿安全技术与漏洞缓解策略
  • label和brand的区别(品牌=brand?错了,你们的英语都学错了!)
  • 读书笔记:更智能的数据库索引:只关注你需要的数据
  • 关于天猫精灵喵控的初步拆机研究
  • C++完全攻略:从新手到高手的编程进化之路 - 详解
  • Visual Studio 报错:“9_自定义命令”名称在默认命名空间“9_自定义命令”中无效。请更正项目文件中的 RootNamespace 标记值。
  • 图解23:datetime和timestamp的区别
  • 在Java中识别泛型信息
  • Kali Linux 光标与快捷键全攻略
  • Docker - ZZH Ubuntu Image - Desktop
  • 图解17:5中网络IO模型
  • 【session反序列化】 - 指南
  • 在k8s集群中解决master节点与node通信
  • PHP中常见数组操作函数
  • 修复Ubuntu系统文件损坏:手动fsck指令
  • window表现驱动开发—视频呈现网络简介