位运算操作

题意:

  • 给两个长度为n的数组a,b,改变b的顺序,使得$(a_i&^&b_i)$&$(a_i&^&b_i)$最大

 

分析:

  • 从高位往低位贪心
  • 如果当前一位a中1的数量和b中0的数量相当,那么说明这一位可以取得
  • 然后把a=1,b=0和a=0,b=1分治,再次重复这个操作
  • 每一块分治都必须满足这个条件才能答案加上这一位2进制

 

技巧:

  • 用二进制分治,通过已经有的ans取出a[i]和b[i]的对应位,容易发现,保留的信息让不同块计算出来的数字高位肯定不同,实现了分治
  • 核心代码 ` cnt[a[i]&ans] ++;cnt[~b[i]&ans] --;`
#include<bits/stdc++.h>
#define debug1(a) cout<<#a<<'='<< a << endl;
#define debug2(a,b) cout<<#a<<" = "<<a<<"  "<<#b<<" = "<<b<<endl;
#define debug3(a,b,c) cout<<#a<<" = "<<a<<"  "<<#b<<" = "<<b<<"  "<<#c<<" = "<<c<<endl;
#define debug4(a,b,c,d) cout<<#a<<" = "<<a<<"  "<<#b<<" = "<<b<<"  "<<#c<<" = "<<c<<"  "<<#d<<" = "<<d<<endl;
#define debug5(a,b,c,d,e) cout<<#a<<" = "<<a<<"  "<<#b<<" = "<<b<<"  "<<#c<<" = "<<c<<"  "<<#d<<" = "<<d<<"  "<<#e<<" = "<<e<<endl;
#define endl "\n"
#define fi first
#define se second

//#define int long long
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;

//#pragma GCC optimize(3,"Ofast","inline")
//#pragma GCC optimize(2)

//常数定义
const double eps = 1e-4;
const double PI = acos(-1.0);
const int N = 1e5+10;
int a[N],b[N];
void solve() 
{
    int n;cin >> n;
    for(int i = 1;i <= n;i ++)cin >> a[i];
    for(int i = 1;i <= n;i ++)cin >> b[i];
    
    int ans = 0;
    for(int k = 30;k >= 0;k --)
    {
        map<int,int> cnt;
        ans += 1<<k;
        for(int i = 1;i <= n;i ++)
        {
            cnt[a[i]&ans] ++;
            cnt[~b[i]&ans] --;
        }
        for(auto &[x,y]:cnt)if(y)
        {
            ans -= 1<<k;
            break;
        }
    }
    int t = 1;
    cout << (~t) << endl;
    cout << ans << endl;
}

signed main()
{
    
    /*
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    */
    int T = 1;cin >> T;

    while(T--){
        //puts(solve()?"YES":"NO");
        solve();
    }
    return 0;

}
/*

*/

 

posted @ 2023-01-22 23:17  俄罗斯刺沙蓬  阅读(10)  评论(0编辑  收藏  举报
返回顶端