提示:
Codeforces Round #618 (Div. 1)-----A. Anu Has a Function
题意:
- 定义一个函数f(x , y) = f(x | y) - y
- 给定一个长度为n的序列a,给序列重新排序,使得f(f…f(f(a1,a2),a3),…an−1),an)的值最大
- n(1≤n≤10^5), ai(0≤ai≤10^9)
解题思路:
上图是计算f(11,6)的过程,可以发现运算结果对于 “11” 的二进制表示就是如果该位在"6"的二进制表示中对应的值是1那么这位就是0,否则不变,然后我们就可以得出f(x,y) = (x | y) - y = x & (~y)
由题中所要求的f(f…f(f(a1,a2),a3),…an−1),an)化简为a1 & (~a2) & (~a3) & (~a4) & … & (~an),要使得这个式子最大,只需要找到一个a1和剩余的式子与最大就ok,假设a1为数组中的第k个,则
最后记录令函数值最大的k,最后a1与ak交换输出序列就ok,时间复杂度为O(n)
解题代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int N = 1e5 + 10;
int n, k, mx = -0x3f3f3f3f, tp;
int sum1[N], sum2[N], a[N];
int main()
{
scanf("%d",&n);
for(int i = 1 ; i <= n ; ++i)
{
scanf("%d",&a[i]);
sum1[i] = sum1[i-1] | a[i];
}
for(int i = n ; i >= 1 ; --i)
sum2[i] = sum2[i+1] | a[i];
for(int i = 1 ; i <= n ; ++i)
if((tp = a[i] & ~(sum1[i-1] | sum2[i+1])) > mx)
mx = tp, k = i;
printf("%d",a[k]);
for(int i = 1 ; i <= n ; ++i)
if(i != k)
printf(" %d",a[i]);
printf("\n");
return 0;
}