A. Min Or Sum(位运算 + 构造)
Description:
对一个数组 任意选择ai aj 用 x y替换他们 不限次数
要求ai | aj == x | y
问操作完毕后数组和的最小值
Method:
将ai aj换到最小 指的是尽量让每个位数上只有一个1
5|6 – > min(0|7)
所以使数列的全部数得到min 但是又要保证位上原有的1不发生改变 那么删去多出来的1即可
在代码上的体现就是|全部数
Code:
void solve()
{
int res = 0;
cin >> n;
while(n--)
{
int x; cin >> x;
res |= x;
}
cout << res << endl;
}
B. Avoid Local Maximums(模拟 + 贪心)
Description:
以最小次数的操作来避免数列中出现山峰
每次操作可以对一个值进行更改
Method:
假设样例3 5 4 7
5是山峰
因为是for过来的 所以改i - 1已经对整体不造成贡献了
我们只能改i + 1 如果说a_i+1 = a_i 那么i就不造成山峰了 但是这样的话 i + 2又有可能变成山峰 所以这时候a_i = max(a_i + 1, a_i + 2)可以使ai 和 a i + 2都不能构成山峰 比选择ai更优
Code:
void solve()
{
int n;
scanf("%d", &n);
vector<int> q(n);
for(int i = 0; i < n; i++) scanf("%d", &q[i]);
int res = 0;
for(int i = 1; i + 1 < n; i++)
{
if(q[i] > q[i - 1] && q[i] > q[i + 1]) //若i是山峰
{
if(i + 2 < n) q[i + 1] = max(q[i], q[i + 2]); // 贪心
else q[i + 1] = q[i];
res ++;
}
}
cout << res << endl;
for(int x : q) printf("%d ",x);
cout << endl;
}
C. Differential Sorting
Description:
给定长度为n的序列 任意选择三个下标x, y, z 将a_x 换成 a_y - a_z
是否能通过操作 构造出单调不降的序列
Method:
If there are multiple solutions, you can output any. Note that you don’t have to minimize the number of operations in this task.请注意,你不必在这项任务中尽量减少操作的数量。
对解题来说非常重要的一句话,这样的话 本来是非常难以抉择去选择最少操作次数的问题 变成了直接考虑最多操作次数的这种情况 这样的情况会非常容易解答
操作次数最多的情况就是让a_1~a_n-2都是同一个数字(a_n - a_n-1)
因为a_n - 1无法被替换 所以正确答案必定有 a_n - 1 <= a_n
当a_n为负数的时候 构造的a_i一定是比a_n-1大的 不符合题意
所以当a_n为负数的时候 除非a已经是单调不降序列 不然都是错误的
当a_n-1 <= a_n && a_n > 0 对1~n-2进行操作即可
Code:
void solve()
{
int n;
scanf("%d", &n);
vector<int> q(n);
for(int i = 0; i < n; i++) scanf("%d", &q[i]);
if(q[n - 2] > q[n - 1]) printf("-1\n");
else
{
if(q[n - 1] < 0)
{
if(is_sorted(q.begin(), q.end())) printf("0\n");
else printf("-1\n");
}
else
{
printf("%d\n", n - 2);
for(int i = 1; i <= n - 2; i++) printf("%d %d %d\n", i, n - 1, n);
}
}
}