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 的分数为该段内所有数异或的 ,即:

需要请你给出如下信息:

  1. 请给出数组 ai 的一个分段方案,使得各段分数的总和最大;
  2. 请给出数组 ai 的一个分段方案,使得各段分数的总和最小。

Input

第一行,一个正整数 n (1 ≤ n ≤ {10}5),表示数组的长度。

第二行,共 n 个非负整数 a1, a2, ..., an (0 ≤ ai < {2}20),表示题目描述中的数组 ai

Output

按顺序输出两个数组分段的方案,第一个方案需使得分数和最大,第二个方案需使得分数和最小。

方案的格式为:

  • 一行,n 个正整数 si (1 ≤ si ≤ n1 ≤ 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
Examples

思路

一次训练赛时见到的这道题,略显复杂的题面让我对题目的难度估计过高,略带慌乱地拿起草稿纸试图找出规律或公式,然而并没有什么结果。

赛后查了一下题解,看到之后只想给当时的自己脑袋一拳让自己清醒清醒

 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”的数量变少或不变,而不会变多。所以分数最大的情况只需要全分段,最小的情况只需要全不分。就这么简单

 

 

题外话:这道题题如其名,所有的样例数据都充满了欺骗性!所有的数据都不按着最方便的思路来,非给一些奇奇怪怪的答案忽悠选手往别的方向上想。

无论什么时候,都要保持冷静,耐心!

 

posted @ 2021-02-06 23:56  icey_z  阅读(135)  评论(0)    收藏  举报