gym102889C 亦或骗子
C. 亦或骗子
https://codeforces.com/gym/102889/problem/C
问题描述
对于非负整数 u, v 的异或 ,w 二进制下第 i 位为 1,当且仅当 u 和 v 二进制下的第 i 位不相同。
非负整数 x 的 ,定义为 x 二进制下 1 的个数,比如
,
,
。
现给一个长度为 n 的数组 a1, a2, ..., an。定义数组连续的一段 al, al + 1, ..., ar 的分数为该段内所有数异或的 ,即:

需要请你给出如下信息:
- 请给出数组 ai 的一个分段方案,使得各段分数的总和最大;
- 请给出数组 ai 的一个分段方案,使得各段分数的总和最小。
Input
第一行,一个正整数 n (1 ≤ n ≤ {10}5),表示数组的长度。
第二行,共 n 个非负整数 a1, a2, ..., an (0 ≤ ai < {2}20),表示题目描述中的数组 ai。
Output
按顺序输出两个数组分段的方案,第一个方案需使得分数和最大,第二个方案需使得分数和最小。
方案的格式为:
- 一行,n 个正整数 si (1 ≤ si ≤ n, 1 ≤ i ≤ n),表示原数组中第 i 个整数分在了第 si 段。需要满足 s1 = 1,以及
注意:方案不需要段数最小或最大,只要各段分数总和最大化或最小化即可。如果有多种方案,则给出任意一种即可。

Examples input 6 6 4 2 4 1 7 output 1 2 3 3 3 4 1 1 1 2 2 2 input 9 3 9 1 10 9 6 7 1 6 output 1 2 3 3 4 4 5 6 6 1 1 1 1 1 2 2 2 3 input 3 0 0 0 output 1 1 1 1 2 3
思路
一次训练赛时见到的这道题,略显复杂的题面让我对题目的难度估计过高,略带慌乱地拿起草稿纸试图找出规律或公式,然而并没有什么结果。
赛后查了一下题解,看到之后只想给当时的自己脑袋一拳让自己清醒清醒
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int n; 6 cin >> n; 7 for (int i = 1; i <= n;i++) 8 cout << i << " "; 9 cout << "\n"; 10 for (int i = 1; i <= n;i++) 11 cout << "1 "; 12 cout << "\n"; 13 return 0; 14 }
代码就这么简单。
道理很简单,对于异或操作,该操作只会让二进制中“1”的数量变少或不变,而不会变多。所以分数最大的情况只需要全分段,最小的情况只需要全不分。就这么简单
题外话:这道题题如其名,所有的样例数据都充满了欺骗性!所有的数据都不按着最方便的思路来,非给一些奇奇怪怪的答案忽悠选手往别的方向上想。
无论什么时候,都要保持冷静,耐心!