2019HDU多校赛第九场H、Rikka with Stable Marriage(Trie树+贪心)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/C20180602_csq/article/details/100189173

Rikka with Stable Marriage

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 242    Accepted Submission(s): 145


 

Problem Description

People in love always feel humble. Sometimes, Rikka is worried about whether she deserves love from Yuta.

Stable marriage problem is an interesting theoretical model which has a strong connection with the real world. Given n men and n women, where each person has ranked all members of the opposite sex in order of preference. We use a permutation p of length n to represent a match that the ith man gets married with the pith woman. A match is stable if and only if there are no two people of opposite sexes who would both rather have each other than their current partners, i.e., ∀i≠j,¬(ri(pj,pi)∧rpj(i,j)) where ra(b,c) represents whether person a loves b more than c.

Rikka wants to resolve the confusion in her mind by considering a special case of the stable marriage problem. Rikka uses a feature integer to represents a person's character, and for two persons with feature integers equal to x and y, Rikka defines the suitable index of them as x⊕y, where ⊕ represents binary exclusive-or.

Given n men with feature integers a1,…,an and n women with feature integers b1,…,bn. For the ith man, he loves the jth woman more than the kth woman if and only if ai⊕bj>ai⊕bk; for the ith woman, she loves the jth man more than the kth man if and only if bi⊕aj>bi⊕ak. 

Rikka wants to calculate the best stable match for this problem, i.e., let P be the set of all stable match, she wants to calculate maxp∈P(∑ni=1(ai⊕bpi)). Since n is quite large, this problem is too difficult for Rikka, could you please help her find the answer?

Input

The first line of the input contains a single integer T(1≤T≤50), the number of test cases.

For each test case, the fisrt line contains a sigle integer n(1≤n≤105). 

The second line contains n integers a1,…,an(1≤ai≤109) which represents the feature number of each man. 

The third line contains n integers b1,…,bn(1≤bi≤109) which represents the feature number of each woman.

The input guarantees that there are no more than 5 test cases with n>104, and for any i,j∈[1,n],i≠j, ai≠aj and bi≠bj.

Output

For each test case, output a single line with a single integer, the value of the best stable match. If there is no stable match, output −1.

Hint

In the first test case, one of the best matches is (2,1,4,3). Therefore the answer is (1⊕2)+(2⊕1)+(3⊕4)+(4⊕3)=20.

Sample Input

2

4

1 2 3 4

1 2 3 4

5

10 20 30 40 50

15 25 35 45 55

Sample Output

20

289

题意

有n个男生,n个女生(n<=100000),每个人有一个权值,每两个人的好感度为a[i]^b[j],求将他们稳定婚姻匹配的最大权值。

题解

考场上只想到了O(n^2)。。。

正解是把两组人分别建两棵Trie树(其实也可以只建一棵),从根节点向下走

贪心地想一下,我们要让异或值最大的话,就应该使他们的路径尽量不同

所以优先使它们走相反方向,进行匹配,统计答案

直到不行时,再走相同方向,统计答案

(这个思路太巧妙了,代码又短)

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100005
#define LOG 30
struct node{
    int x,l,r,siz1,siz2;
    void clear(){x=l=r=siz1=siz2=0;}
}a[N*LOG];
int tot,rt;
void pushup(int i)
{
    a[i].siz1=a[a[i].l].siz1+a[a[i].r].siz1;
    a[i].siz2=a[a[i].l].siz2+a[a[i].r].siz2;
}
void insert(int &i,int x,int dep,int flg)
{
    if(!i)a[i=++tot].clear();
    if(!dep){
        a[i].x=x;
        if(flg) a[i].siz1++;
        else a[i].siz2++;
        return;
    }
    if(x&(1<<(dep-1))) insert(a[i].r,x,dep-1,flg);
    else insert(a[i].l,x,dep-1,flg);
    pushup(i);
}
long long ans;
void match(int i,int j,int dep)
{
    if(!a[i].siz1||!a[j].siz2) return;
    if(!dep){
        int tmp=min(a[i].siz1,a[j].siz2);
        a[i].siz1-=tmp;a[j].siz2-=tmp;
        ans+=1ll*tmp*(a[i].x^a[j].x);
        return;
    }
    match(a[i].l,a[j].r,dep-1);
    match(a[i].r,a[j].l,dep-1);
    match(a[i].l,a[j].l,dep-1);
    match(a[i].r,a[j].r,dep-1);
    pushup(i);pushup(j);
}
int main()
{
    int T,n,i,x;
    scanf("%d",&T);
    while(T--){
        rt=tot=0;ans=0;
        scanf("%d",&n);
        for(i=1;i<=n;i++){
            scanf("%d",&x);
            insert(rt,x,30,1);
        }
        for(i=1;i<=n;i++){
            scanf("%d",&x);
            insert(rt,x,30,0);
        }
        match(rt,rt,30);
        printf("%lld\n",ans);
    }
}

Trie树真好用

猜你喜欢

转载自blog.csdn.net/C20180602_csq/article/details/100189173
今日推荐