P11233 [CSP
来源: 时间:2026-01-06 17:06
<think>我们参考用户的问题,他询问的是2024年CSP-S(提高级)认证中的染色问题(P11233)的解法。根据引用[1]中的描述,题目要求是最大化相邻同色元素的最小值之和。通过分析,我们得到以下关键点: 1. 题目规则:当两个相同颜色的元素相邻,且它们之间没有其他同色元素时,得分等于这两个元素的值的最小值。 2. 观察:为了最大化得分,我们应该将相同数值的元素染成同一种颜色(红色或蓝色),并且将它们连续放置(即相邻),这样每个数值(除了第一个)都能与它前面最近的一个相同数值形成有效对。 3. 独立贡献:不同数值之间的贡献是独立的。对于每个数值v,如果它出现了cnt_v次,那么它最多可以形成(cnt_v-1)对相邻的同色元素。每一对的贡献是v(因为两个数都是v,最小值就是v),所以该数值的总贡献为v*(cnt_v-1)。 因此,整个问题的解法如下: 1. 统计每个数值出现的次数(注意数值范围,题目中最大值为10^6)。 2. 遍历所有数值,对于出现次数大于等于2的数值,计算其贡献:v*(cnt_v-1),并累加。 3. 输出总和。 注意:题目中可能有多个测试用例,所以需要处理T组数据。 代码实现时,我们使用一个长度为MAX_VAL+1的数组cnt(初始化为0)来统计每个数值的出现次数。然后读入数组,对于每个数a,如果a在范围内(<=MAX_VAL),则cnt[a]++。最后遍历1到MAX_VAL,累加贡献。 下面给出代码(已根据题目要求使用C++):</think>### 2024 CSP-S 染色问题解法详解(P11233) #### 核心思路 题目要求最大化相邻同色元素的最小值之和。通过分析规则,发现得分仅发生在相同数值的相邻位置(中间无同色元素)上,且**每个数值的贡献独立**。关键结论如下: 1. **同色聚合最优**:对于数值 $v$,将所有 $v$ 染成同色时贡献最大 - 例:`[5,2,5]` 染同色得 $5$(`5-5`),分色则得 $0$ 2. **贡献公式**:数值 $v$ 出现 $cnt_v$ 次时,最大贡献为: $$ text{贡献}(v) = begin{cases} v times (cnt_v - 1) & text{if } cnt_v geq 2 \ 0 & text{otherwise} end{cases} $$ - 每对相邻同色元素贡献 $v$(因 $min(v,v)=v$) - $cnt_v$ 个元素可形成 $(cnt_v-1)$ 对有效相邻 #### 算法步骤 1. **频率统计** 遍历数组,统计每个数值出现次数 $cnt_v$ ```cpp vector<int> cnt(MAX_VAL + 1, 0); for (int i = 0; i < n; i++) { cin >> a; if (a <= MAX_VAL) cnt[a]++; } ``` 2. **贡献计算** 对每个 $v in [1, text{MAX_VAL}]$ 计算贡献: ```cpp long long ans = 0; for (int v = 1; v <= MAX_VAL; v++) { if (cnt[v] >= 2) { ans += static_cast<long long>(v) * (cnt[v] - 1); } } ``` 3. **输出结果** 直接输出累加值 `ans` #### 复杂度分析 - **时间**:$O(n + text{MAX_VAL})$ - 统计频率 $O(n)$,计算贡献 $O(text{MAX_VAL})$ - **空间**:$O(text{MAX_VAL})$ 频率数组空间 #### 正确性验证 **样例输入**:`[3, 5, 2, 5, 1, 2, 1, 4]` - $1$:出现 $2$ 次 → $1 times (2-1) = 1$ - $2$:出现 $2$ 次 → $2 times (2-1) = 2$ - $5$:出现 $2$ 次 → $5 times (2-1) = 5$ - 其他值:$cnt < 2$ → $0$ **总得分**:$1 + 2 + 5 = 8$(最优解:所有 $1,2,5$ 染同色)[^1] #### 优化扩展 1. **大数值范围($v leq 10^9$)** 改用 `map` 统计频率: ```cpp unordered_map<int, int> cnt; for (int i = 0; i < n; i++) { cin >> a; cnt[a]++; } // 遍历map计算贡献 ``` - 时间:$O(n log n)$,空间:$O(n)$ 2. **动态规划解法(备用思路)** 当规则复杂化时(如连续段极差),可用 DP: ```cpp // dp[i][c]: 前i个元素,末尾颜色为c时的最大得分 for (int i = 1; i <= n; i++) { for (int c : {RED, BLUE}) { dp[i][c] = max( dp[i-1][c] + score(a[i], c), // 延续同色 dp[i-1][!c] // 切换颜色 ); } } ``` 但本题证明独立贡献更优[^2],无需 DP #### 代码实现 ```cpp #include <iostream> #include <vector> using namespace std; const int MAX_VAL = 1000000; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T--) { int n; cin >> n; vector<int> cnt(MAX_VAL + 1, 0); for (int i = 0; i < n; i++) { int a; cin >> a; if (a <= MAX_VAL) cnt[a]++; } long long ans = 0; for (int v = 1; v <= MAX_VAL; v++) { if (cnt[v] >= 2) { ans += static_cast<long long>(v) * (cnt[v] - 1); } } cout << ans << 'n'; } return 0; } ``` ### 相关问题 1. **若染色规则改为取相邻同色元素的最大值,解法如何调整?** **答**:贡献公式不变,仍为 $v times (cnt_v-1)$(因 $max(v,v)=v$)[^1] 2. **多颜色(如三种)时能否增加得分?** **答**:不能。分组会减少有效数对数量,同色聚合仍最优(例:三个 $5$ 分两色最多得 $5$,同色得 $5 times 2=10$) 3. **贪心策略为何无效?请举例说明** **答**:顺序染色无法保证全局最优。例 `[2,1,2]`: - 贪心:染 `[红,蓝,红]` 得 $min(2,2)=2$ - 最优:全染红得 $2 times (2-1)=2$(但若为 `[1,2,1]`,贪心可能得 $0$,最优得 $1$) 4. **若得分规则改为连续同色段的极差之和,如何设计算法?** **答**:需动态规划维护段信息: ```python # dp[i][c] = (当前段最小值, 当前段最大值, 总得分) for i in range(n): for c in colors: # 延续当前颜色段 new_min = min(dp[i-1][c].min, a[i]) new_max = max(dp[i-1][c].max, a[i]) score_add = new_max - new_min # 或新开颜色段 ... ``` 5. **如何应对元素删除/修改的变种问题?** **答**:需线段树维护区间频率,结合莫队算法处理动态询问($O(nsqrt{n})$)[^3]
相关知识
P11233 [CSP
共价结合型果胶(CSP)可见分光光度法
CSP
[CSP
Omdia观点:目录管理对于电信运营商扩大市场至关重要
P5662 [CSP
插画下载哪些app?请问大家,目前最流行的插画设计软件是哪个?
复(混)合肥
题解 P5662 [CSP
不同枇杷品种果实发育过程中果肉细胞壁组分的变化
网址: P11233 [CSP https://www.huajiangbk.com/newsview2534687.html
| 上一篇: 植根人民沃土 茉莉香飘世界——原 |
下一篇: 通达信再战股海指标民间操手专用经 |
推荐分享
- 1君子兰什么品种最名贵 十大名 4012
- 2世界上最名贵的10种兰花图片 3364
- 3花圈挽联怎么写? 3286
- 4迷信说家里不能放假花 家里摆 1878
- 5香山红叶什么时候红 1493
- 6花的意思,花的解释,花的拼音 1210
- 7教师节送什么花最合适 1167
- 8勿忘我花图片 1103
- 9橄榄枝的象征意义 1093
- 10洛阳的市花 1039
分享热点排名
