UOJ #1005. 【UR #32】王之钦定 题解

news/2025/10/20 16:58:52/文章来源:https://www.cnblogs.com/Scarab/p/19153011

Description

跳蚤国计算机协会 UOI 主席 “王中王” 认为 UOI 决赛不具有观赏性。

比如蟋蟀国的比赛,选手都需要在初赛快速 AK 才能晋级决赛,但 UOI 决赛只需要通过不到一半的题目就可以获得三十二强。

但是经过 UOI 系列委员会的商讨,比赛难度并没有被下调,因此王中王决定黑幕一些比赛结果。

具体来说,UOI 决赛总 \(n\) 天,有 \(m\) 名选手参加。现在王中王通过第六感得知,如果不加干预第 \(i\) 天的比赛,那么第 \(a_i\) 位选手将会胜出,但王中王每天可以将当天题目提前透露给任意一名选手。如果王中王透露了第 \(i\) 天的题目,获得题目的选手将会成为那天比赛的胜利者,但他认为这样做比赛的合理性会降低 \(w_i\)

不妨假设黑幕后每天的胜者依次为 \(b_1, b_2, \dots, b_n\)。王中王相信观众更喜欢看到“绝对强者”之间的对决,因此他认为一段赛程 \([l, r]\) 是“好看”的,当且仅当在该段赛程中,成为过胜者的选手数不超过二,即 \(|\{b_l, b_{l+1}, \dots, b_r\}| \leq 2\)

而每一段“好看”的赛程,王中王认为都会让比赛的合理性增加 \(1\)

而由于 UOI 决赛随时面临着缺投倒闭的风险,因此王中王想知道对于所有 \(k = 1, 2, \dots, n\),如果 UOI 决赛只举办前 \(k\) 天的比赛,比赛的合理性最高能是多少?

\(1 \leq n \leq 1500, 1 \leq a_i \leq m\leq 50, 0 \leq w_i \leq 10^6\)

Solution

定义一个区间 \([l,r]\) 是好的,当且仅当 \([l,r]\) 中颜色数量不超过 \(2\),把所有极长好区间拿出来,设其为 \([l_1,r_1],[l_2,r_2],\ldots,[l_k,r_k]\)

不妨设 \(l_1<l_2<\ldots<l_k\)\(r_1<r_2<\ldots<r_k\),则 \([l_i,r_i]\)\([l_{i+1},r_{i+1}]\) 一定有交,且交是一段极长颜色连续段。同时 \([l_i,r_i]\) 与其相邻的两个区间的两个交一定没有交集,否则 \([l_i,r_i]\) 颜色就全相同了,可以和相邻的区间合并。

钦定 \([l_i,r_i]\) 中出现的颜色为 \(1\)\(2\),定义 \([l_i,r_i]\) 的中间部分是整个区间去掉与相邻区间的交后剩下的区间,容易发现中间部分的两端点一定没有被操作,否则操作成与相邻区间的交的颜色一定更优。考虑分讨 \([l_i,r_i]\) 与相邻区间的交集的颜色情形:

  1. \(111\,222\):此时中间部分大小为 \(0\),前半部分是与 \(i-1\) 的交,后半部分是与 \(i+1\) 的交。
  2. \(111\,21\,222\):中间部分非空,且与 \(i-1\) 的交的颜色和与 \(i+1\) 的交的颜色不同。
  3. \(111\,212\,111\):中间部分非空,且与 \(i-1\) 的交的颜色和与 \(i+1\) 的交的颜色相同。

由于对于一段区间,我们只关心这个区间与下一个区间交的部分的状态,所以可以对这个设计状态。

\(f_{i,j,c}\) 表示目前考虑了一个极长好区间,右端点为 \(j\),钦定与下一段好区间的交是 \([i,j]\),且颜色为 \(c\) 时,\([1,j]\) 的最优贡献。考虑按照左端点从小到大进行转移,

对于第一种情况可以直接枚举下一段交区间的长度和颜色来转移。

对于第二/三种情况,需要加上中间部分的贡献,直接枚举的话转移到后面的交区间之前都要 \(O(n^3m)\) 。考虑加入辅助状态,设 \(g_{x,y,c_1,c_2}\) 表示对于所有左端点为 \(x\),右端点小于等于 \(y\) 的交区间,钦定后面这段区间的两种颜色是 \(c_1,c_2\) 时,\([1,y]\) 的最优贡献。这个辅助状态可以在从小到大枚举左端点的时候一起转移,时间复杂度是 \(O(n^2m^2)\)

得到 \(g\) 的值后,枚举第二段交区间的长度和颜色以及区间内出现的另一个颜色后转移就和第一种情况就差不多了,但是会比第一种情况多一个 \(m\)

设钦定的第二段交区间是 \([i',j']\),根据上面的性质,中间部分的两端点都不会被操作,所以区间内的另一个颜色一定就是 \(i'-1\) 的初始颜色 \(a_{i'-1}\),复杂度也就变得和第一种情况一样了。

推一下会发现直接转移是 \(O(n^3m)\) 的,注意到转移是最大化 \(k_ix+b_i\) 的形式,同时 \(x\) 单调递增,所以维护关于 \((k_i,b_i)\) 的上凸壳,再在凸壳上维护一个指针表示当前最优的 \((k_i,b_i)\) 即可。

时间复杂度:\(O(n^2m^2)\),瓶颈是 \(g\) 的转移,常数很小,可以过。

具体实现细节见代码。

Code

#include <bits/stdc++.h>// #define int int64_ttemplate<class T>
struct Vector {T x, y;Vector() {}Vector(T _x, T _y) : x(_x), y(_y) {}friend bool operator ==(Vector a, Vector b) { return a.x == b.x && a.y == b.y; }friend bool operator !=(Vector a, Vector b) { return a.x != b.x || a.y != b.y; }friend Vector operator -(Vector a) { return {-a.x, -a.y}; }friend Vector operator +(Vector a, Vector b) { return {a.x + b.x, a.y + b.y}; }friend Vector operator -(Vector a, Vector b) { return {a.x - b.x, a.y - b.y}; }friend T operator *(Vector a, Vector b) { return a.x * b.y - a.y * b.x; }template<class _T> friend Vector operator *(Vector a, _T b) { return {a.x * b, a.y * b}; }template<class _T> friend Vector operator *(_T a, Vector b) { return {a * b.x, a * b.y}; }template<class _T> friend Vector operator /(Vector a, _T b) { return {a.x * 1.0 / b, a.y * 1.0 / b}; }friend Vector operator +=(Vector &a, Vector b) { return a = {a.x + b.x, a.y + b.y}; }friend Vector operator -=(Vector &a, Vector b) { return a = {a.x - b.x, a.y - b.y}; }template<class _T> friend Vector operator *=(Vector &a, _T b) { return a = {a.x * b, a.y * b}; }template<class _T> friend Vector operator /=(Vector &a, _T b) { return a = {a.x * 1.0 / b, a.y * 1.0 / b}; }friend bool operator <(Vector a, Vector b) { return a.x < b.x || a.x == b.x && a.y < b.y; }
};using i64 = int64_t;
using Vec = Vector<i64>;const int kMaxN = 1.5e3 + 5, kMaxK = 55;int n, m;
int a[kMaxN], w[kMaxN], sum[kMaxN], pre[kMaxK][kMaxN], f[kMaxN][kMaxN][kMaxK], g[kMaxN][kMaxK][kMaxK];inline void chkmax(int &x, int y) { x = (x > y ? x : y); }
inline void chkmin(int &x, int y) { x = (x < y ? x : y); }int getval(int c1, int c2, int l, int r) {if (c1 == c2) c2 = 0;return sum[r] - sum[l - 1] - (pre[c1][r] - pre[c1][l - 1]) - (pre[c2][r] - pre[c2][l - 1]);
}int calc(Vec p, int x) { return x * p.x + p.y; } void dickdreamer() {std::cin >> n >> m;for (int i = 1; i <= n; ++i) std::cin >> a[i];for (int i = 1; i <= n; ++i) {std::cin >> w[i];sum[i] = sum[i - 1] + w[i];for (int j = 1; j <= m; ++j)pre[j][i] = pre[j][i - 1] + w[i] * (j == a[i]);}memset(f, 0xcf, sizeof(f));memset(g, 0xcf, sizeof(g));for (int i = 1; i <= n; ++i) {for (int c1 = 1; c1 <= m; ++c1) {int mi = 1e9;for (int c2 = 1; c2 <= m; ++c2) chkmin(mi, getval(c1, c2, 1, i));for (int j = i + 1; j <= n; ++j) {chkmax(f[i + 1][j][c1], 1ll * j * (j + 1) / 2 - mi - getval(c1, c1, i + 1, j));}}}for (int i = 2; i < n; ++i) {for (int j = 2; j <= i; ++j) {for (int c1 = 1; c1 <= m; ++c1) {for (int c2 = c1; c2 <= m; ++c2) {chkmax(g[j][c1][c2], std::max(f[j][i - 1][c1], f[j][i - 1][c2]));g[j][c1][c2] += (i - j + 1) - (a[i] != c1 && a[i] != c2) * w[i];}}}{static int mx[kMaxN];for (int j = 2; j <= i; ++j) {mx[j] = -1e9;for (int c = 1; c <= m; ++c) chkmax(mx[j], f[j][i][c]);}for (int c = 1; c <= m; ++c) {std::vector<Vec> stk;for (int k = i; k >= 2; --k) {Vec p = {i - k + 1, mx[k]};for (; stk.size() >= 2 && (p - stk.back()) * (stk.back() - stk[stk.size() - 2]) <= 0; stk.pop_back()) {}stk.emplace_back(p);}for (int j = i + 1, pos = 0; j <= n; ++j) {int now = (j - i) * (j - i + 1) / 2 - getval(c, c, i + 1, j);// for (int k = 2; k <= i; ++k) chkmax(f[i + 1][j][c], mx[k] + now + (j - i) * (i - k + 1));for (; pos + 1 < stk.size() && calc(stk[pos + 1], j - i) > calc(stk[pos], j - i); ++pos) {}chkmax(f[i + 1][j][c], now + calc(stk[pos], j - i));}}}for (int c = 1; c <= m; ++c) {int c1 = std::min(c, a[i]), c2 = std::max(c, a[i]);std::vector<Vec> stk;for (int k = i; k >= 2; --k) {Vec p = {i - k + 1, g[k][c1][c2]};for (; stk.size() >= 2 && (p - stk.back()) * (stk.back() - stk[stk.size() - 2]) <= 0; stk.pop_back()) {}stk.emplace_back(p);}for (int j = i + 1, pos = 0; j <= n; ++j) {int now = (j - i) * (j - i + 1) / 2 - getval(c, c, i + 1, j);// for (int k = 2; k <= i; ++k) chkmax(f[i + 1][j][c], mx[k] + now + (j - i) * (i - k + 1));for (; pos + 1 < stk.size() && calc(stk[pos + 1], j - i) > calc(stk[pos], j - i); ++pos) {}chkmax(f[i + 1][j][c], now + calc(stk[pos], j - i));}}}for (int i = 1; i <= n; ++i) {if (i == 1) {std::cout << 1 << ' ';} else {int ans = -1e9;for (int j = 2; j <= i; ++j)for (int c = 1; c <= m; ++c)chkmax(ans, f[j][i][c]);std::cout << ans << ' ';}}
}int32_t main() {
#ifdef ORZXKRfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
#endifstd::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);int T = 1;// std::cin >> T;while (T--) dickdreamer();// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/941372.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《C++ string类深度解析:核心接口全方位精讲与掌握》 - 指南

《C++ string类深度解析:核心接口全方位精讲与掌握》 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Cons…

HL7v3和RIM是什么,和传统HL7,FHIR有什么关系

简单来说,可以把它们看作是医疗信息标准演进的三个主要阶段:HL7 V2.x(传统HL7):“实用主义”的行业标准 - 像方言,灵活但不够严谨。 HL7 V3 RIM:“理想主义”的理论基础 - 试图创建一门完美的“世界语”的语法和…

2025 年防撞护栏生产厂家最新推荐排行榜:聚焦铝合金 / Q235/Q355B 桥梁等多类型护栏,精选优质企业

引言 当前交通基础设施建设不断推进,防撞护栏作为保障道路与桥梁安全的核心设施,市场需求持续增长。但市场上厂家数量繁杂,产品质量、生产能力和服务水平差异显著,采购方常面临原材料以次充好、产能不足延误工期、…

AtCoder AGC047 总结

AtCoder AGC047 总结 A 由于小数位最多九位,我们先乘 \(10^9\),转化为求 \(10^{18}\mid a_ia_j\) 的个数。 考虑分解质因数,要求 \(2,5\) 的次数都至少为 \(18\) 即可。时间 \(18^2\times n\)。 B 一个串可以变成的…

YAML

YAML《yaml在嵌入式软件开发中的作用》 YAML:轻量级的数据序列化语言。

QUALIFY 窗口过滤 - --

传统方式(使用CTE):sqlWITH ranked_data AS (SELECT user_id,ip,country_code,os,RANK() OVER (PARTITION BY user_id ORDER BY log_datetime DESC) AS previous_loginsFROM login_logs ) SELECT user_id, ip, coun…

【ffmpeg】开发过程中错误简单记录

最近遇到了些ffmpeg的错误,有些意想不到,有些也很低级,但很多遇到了很难排查到特此记录下。 1、avformat_new_stream 的 Function not implemented错误 打包放到实机的时候发现,无法开启录制,只要录制就报错Funct…

2025 定制家具厂家推荐榜:定制酒柜/定制房门/定制护墙板/定制吧台/定制装饰柜/定制鞋柜/聚焦个性化与环保,这家深圳企业成优选​

随着消费升级持续推进,85 后、90 后成为家居消费核心客群,定制家具因能适配不同户型空间与个性化需求,已从高端市场逐步普及至普通家庭。2025 年,在 “以旧换新” 政策拉动与旧房翻新需求释放下,定制家具市场规模…

Winform开发报表(锐浪推方式)

Grid++Report 的报表数据来源既可以是推(PUSH)模式,也可以是拉(PULL)模式。所谓推模式就是由报表宿主程序向报表填充数据,报表引擎处于被动接受数据的形式。所谓拉模式就是报表引擎根据报表的数据源取数参数主动从数…

2025年通风天窗厂家最新权威推荐榜:排烟天窗、通风气楼、屋顶通风器、顺坡气楼、10A通风天窗、1型通风天窗、TC5A通风天窗、TC12B通风天窗、屋脊通风天窗专业选购指南

2025年通风天窗厂家最新权威推荐榜:排烟天窗、通风气楼、屋顶通风器、顺坡气楼、10A通风天窗、1型通风天窗、TC5A通风天窗、TC12B通风天窗、屋脊通风天窗专业选购指南 随着工业建筑环境标准的不断提升,通风天窗作为工…

【LeetCode】125. 验证回文串

125. 验证回文串 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s,如果它是 回…

Toposort

拓扑排序 今天2025.10.16经过 \(hwh\) 和 \(cxy\) 的指导,我也是初步学会了 \(markdown\),必须得写一篇文章练练手。写得格式可能不太好,没逝,一定会好起来的好了,开始说说今天学的东西—— 拓扑排序 事实上我早就…

2025年冲压件厂家权威推荐榜:新能源/光伏/精密/异形/五金/铝/汽配/不锈钢/家具冲压件源头企业深度解析

2025年冲压件厂家权威推荐榜:新能源/光伏/精密/异形/五金/铝/汽配/不锈钢/家具冲压件源头企业深度解析 一、行业背景与发展趋势 随着制造业的转型升级,冲压件行业正迎来新一轮技术变革。在新能源、光伏、汽车、家电等…

AI 产品测试企业内训 | 两天构建企业级智能体测试能力

关注 霍格沃兹测试学院公众号,回复「资料」, 领取人工智能测试开发技术合集 AI 产品和智能体的快速迭代,给企业测试团队带来了新的挑战: 智能体问答错误率高、插件调用效果不可控 语音识别、文本理解、视觉分析准确…

详细介绍:《掰开揉碎讲编程-短篇》 2025 汉化idea控制台出现乱码解决方案 看完这篇解决不了乱码也是神人了

详细介绍:《掰开揉碎讲编程-短篇》 2025 汉化idea控制台出现乱码解决方案 看完这篇解决不了乱码也是神人了pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display…

探索无限可能:生成式推荐的演进、前沿与挑战【AI业务应用方向】

TL;DR 过去一年间,生成式推荐取得了长足的实质性进展,特别是在凭借大型语言模型强大的序列建模与推理能力提升整体推荐性能方面。基于LLM(Large Language Models, LLMs)的生成式推荐(Generative Recommendations,…

【隐语SecretFlow架构解读】隐私保护模型在线推理系统 SecretFlow-Serving 架构解读

打开链接点亮社区Star,照亮技术的前进之路。每一个点赞,都是社区技术大佬前进的动力Github 地址: https://github.com/secretflow 在传统机器学习场景中,完成模型训练得到模型之后,如何将模型的推理能力应用到实际…

2025年储罐厂家权威推荐榜:钢衬塑储罐,钢塑复合储罐,化工储罐,防腐储罐,PE储罐,盐酸储罐,硫酸储罐,聚丙烯储罐,不锈钢储罐,次氯酸钠储罐

2025年储罐厂家权威推荐榜:钢衬塑储罐,钢塑复合储罐,化工储罐,防腐储罐,PE储罐,盐酸储罐,硫酸储罐,聚丙烯储罐,不锈钢储罐,次氯酸钠储罐 在现代化工、制药、环保等工业领域,储罐作为关键的基础设施,其性能…

多晶硅

等待49700一线 企稳多单

2025 最新推荐!溴化锂回收公司精选榜单:制冷机 / 溶液 / 机组回收服务商权威测评及选择指南

引言 伴随 “双碳” 目标推进与溴化锂制冷设备迭代加速,2025 年国内废旧溴化锂机组、溶液回收需求同比增长 20%,但市场仍存在服务标准混乱、环保合规性参差不齐等问题。部分机构缺乏专业拆解技术,导致铜铝资源回收率…