D. Maximum AND
标签:二进制 数据结构
题意:
- 分别给出长度为n的数组a和数组b,可对数组b重新排序
- 有数组c, c[i] = a[i] ⊕ b[i]
- 求 c[1]&c[2]…&c[n]的最大值
思路:
这题比我写的上一篇简单
比赛时想到了贪心+分治的思路,对位由高倒底进行贪心
先开始分别统计第i位两个数组中 0,1 的数量情况,
若数组a的1的个数等于数组b的0的个数,即数组a的0的个数等于数组b的1的个数,该位就可以得到1
将数组排序,按0,1分成两段,使数组a第i位为1的数的下标和b中第i位为0的数的下标相同
下一位时再对分出的段进行讨论,若每段条件成立,每段再分两段,以此类推
上面这个想法来不及实现,比赛后去看了jls的做法被薄纱了
我的想法中每次讨论0,1数量时受上一次分段的影响,因此需要不断维护数组
大佬的做法中用x=ans | 1 << i
这一步就直接继承了之前分段的结果,然后数组排个序比较就行了
代码:
#define fst std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout << std::fixed << std::setprecision(20)
#define le "\n"
#define ll long long
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
const int mod=1e9+7;
void solve(){
int n; cin>>n;
vector<int> a(n),b(n);
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) cin>>b[i];
ll ans = 0;
for(int i=30; i>=0; i--)
{
int x=ans | 1 << i;
vector<int> c(n), d(n);
for (int j = 0; j < n; j++) {
c[j] = a[j] & x;
d[j] = ~b[j] & x;
}
sort(c.begin(), c.end());
sort(d.begin(), d.end());
if(c == d) {
ans |= 1ll << i;
}
}
cout << ans << le;
}
int main() {
int t; cin>>t;
while(t--){
solve();
}
return 0;
}