hdu 6625 three arrays

这道题的贪心想法是这样的,我们希望产生的最小值越多越好,那么如果对于当前的某一位,同时走 1 或者同时 走 0 的匹配一定比 一个走1,一个走 0 的 要小,那么一直执行这样一个递归的过程,我们就可以得到最小的值。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 20000001;
vector<LL> ve;
struct T{
    int tot = 0,ch[maxn][2],cnt[maxn];
    LL val[maxn];
    void init(){
        for( int i =0;i <= tot;i++ ){
            ch[i][0] = ch[i][1] = cnt[i] = 0;
        }
        tot = 0;
    }
    void insrt( int x,int d,LL v ){
        if( d == -1 ){
            val[x] = v;
            cnt[x]++;
            return;
        }
        int dir = v>>d&1;
        if(!ch[x][dir]) ch[x][dir] = ++tot;
        insrt( ch[x][dir],d-1,v );
        cnt[x] = (ch[x][0]?cnt[ ch[x][0] ]:0) + (ch[x][1]?cnt[ ch[x][1] ]:0);
    }
}g1,g2;
void solve( int x,int y ){
    if( !g1.ch[x][0]&&!g1.ch[x][1] ){
        int mn = min( g1.cnt[x],g2.cnt[y] );
        for( int i = 1;i <= mn;i++  )ve.push_back( g1.val[ x ]^g2.val[y] );
        g1.cnt[x] -=mn;  g2.cnt[y] -=mn ;
        return;
    }
    if( g1.cnt[ g1.ch[x][0] ]&& g1.ch[x][0] &&g2.cnt[g2.ch[y][0] ] && g2.ch[y][0] ){
        solve( g1.ch[x][0],g2.ch[y][0] );
    }
    if( g1.cnt[ g1.ch[x][1] ]&&g1.ch[x][1] &&g2.cnt[g2.ch[y][1] ]&& g2.ch[y][1] ){
        solve( g1.ch[x][1],g2.ch[y][1] );
    }
    if( g1.ch[x][0]&&g1.cnt[ g1.ch[x][0] ] && g2.ch[y][1]&&g2.cnt[ g2.ch[y][1] ] ){
        solve( g1.ch[x][0],g2.ch[y][1] );
    }
    if( g1.ch[x][1]&&g1.cnt[ g1.ch[x][1] ] && g2.ch[y][0]&&g2.cnt[ g2.ch[y][0] ] ){
        solve( g1.ch[x][1],g2.ch[y][0] );
    }
    g1.cnt[x] = (g1.ch[x][0]?g1.cnt[ g1.ch[x][0] ]:0) + (g1.ch[x][1]?g1.cnt[ g1.ch[x][1] ]:0);
    g2.cnt[y] = (g2.ch[y][0]?g2.cnt[ g2.ch[y][0] ]:0) + (g2.ch[y][1]?g2.cnt[ g2.ch[y][1] ]:0);
}
LL a[maxn],b[maxn];
int main(){
    int T,n;
    scanf("%d",&T);
    while(T--){
        ve.clear();g1.init();g2.init();
        scanf("%d",&n);
        for( int i = 1;i <= n;i++ ){
            scanf("%lld",&a[i]);
            g1.insrt( 0,30,a[i] );
        }
        for( int i = 1;i <= n;i++ ) {
            scanf("%lld",&b[i]);
            g2.insrt( 0,30,b[i] );
        }

        solve( 0,0 );
        sort( ve.begin(),ve.end() );
        printf("%lld",ve[0]);
        for( int i =1; i < ve.size();i++ ){
            printf(" %lld",ve[i]);
        }
        printf("\n");
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值