hdu6687 Rikka with Stable Marriage 2019杭电多校第9场

6 篇文章 0 订阅

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6687

题解传送门:https://blog.csdn.net/liufengwei1/article/details/98536161

8说了,原题竟然没有人开,我看都没看。。。

claris还说第五场这题过了76个这场怎么就过了8个。。。

那题求最小,这题求最大,改改finda和findb函数中对字典树的路径选择就过了


#include<bits/stdc++.h>
#define maxl 100010
using namespace std;
 
int n,m,tota,totb,sum;
int ans[maxl],mi[30];
int a[maxl],b[maxl];
int suma[maxl*31],sumb[maxl*31];
int tra[maxl*31][2],trb[maxl*31][2];
int q[maxl],w[maxl];
vector <int> numa[maxl*31],numb[maxl*31];
vector <int> :: iterator it;
bool ina[maxl],inb[maxl];
 
inline void inserta(int id,int x)
{
    int u=0,c;
    for(int i=30;i>=0;i--)
    {
        suma[u]++;
        c=(x>>i)&1;
        if(!tra[u][c])
            tra[u][c]=++tota;
        u=tra[u][c];
    }
    suma[u]++;numa[u].push_back(id);
}
 
inline void insertb(int id,int x)
{
    int u=0,c;
    for(int i=30;i>=0;i--)
    {
        sumb[u]++;
        c=(x>>i)&1;
        if(!trb[u][c])
            trb[u][c]=++totb;
        u=trb[u][c];
    }
    sumb[u]++;numb[u].push_back(id);
}
 
inline void prework()
{
    for(int i=0;i<=tota;i++)
    {
        tra[i][0]=tra[i][1]=0;
        suma[i]=0;numa[i].clear();    
    }
    for(int i=0;i<=totb;i++)
    {
        trb[i][0]=trb[i][1]=0;
        sumb[i]=0,numb[i].clear();
    }
    scanf("%d",&n);
    tota=0;totb=0;
    for(int i=1;i<=n;i++)
    {    
        scanf("%d",&a[i]);
        inserta(i,a[i]);ina[i]=true;
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&b[i]);
        insertb(i,b[i]);inb[i]=true;
    }
}
 
inline int finda(int x)
{
    int u=0,c,tmp=0;
    for(int i=30;i>=0;i--)
    {
        c=(x>>i)&1;
        if(tra[u][c^1])
            u=tra[u][c^1];
        else 
            u=tra[u][c];
    }
    it=numa[u].end();--it;
    return (*it);
}
 
inline int findb(int x)
{
    int u=0,c;
    for(int i=30;i>=0;i--)
    {
        c=(x>>i)&1;
        if(trb[u][c^1])
            u=trb[u][c^1];
        else
            u=trb[u][c];
    }
    it=numb[u].end();--it;
    return (*it);
}
 
inline void dela(int x)
{
    int u=0,c,last;suma[u]--;
    for(int i=30;i>=0;i--)
    {
        c=(x>>i)&1;last=u;
        u=tra[u][c];
        suma[u]--;
        if(suma[u]==0)
            tra[last][c]=0;
    }
    it=numa[u].end();--it;
    numa[u].erase(it);
}
 
inline void delb(int x)
{
    int u=0,c,last;sumb[u]--;
    for(int i=30;i>=0;i--)
    {
        c=(x>>i)&1;last=u;
        u=trb[u][c];
        sumb[u]--;
        if(sumb[u]==0)
            trb[last][c]=0; 
    }
    it=numb[u].end();--it;
    numb[u].erase(it);
}
 
inline void dfs(int k)
{
    int id;
    if(k&1)
    {
        id=finda(b[q[k-1]]);
        if(id==q[k-2] && k-2>0)
        {
            delb(b[q[k-1]]);
            dela(a[id]);
            inb[q[k-1]]=false;
            ina[id]=false;
            ans[++ans[0]]=b[q[k-1]]^a[id];
            k-=2;sum--;
        }
        else
        {
            w[k]=b[q[k-1]]^a[id];
            q[k]=id;k++;
        }
        if(sum>0)
            dfs(k);
    }
    else
    {
        id=findb(a[q[k-1]]);
        if(id==q[k-2] && k-2>0)
        {
            dela(a[q[k-1]]);
            delb(b[id]);
            ina[q[k-1]]=false;
            inb[id]=false;
            ans[++ans[0]]=a[q[k-1]]^b[id];
            k-=2;sum--;
        }
        else
        {
            w[k]=a[q[k-1]]^b[id];
            q[k]=id;k++;
        }
        if(sum>0)
            dfs(k);
    }
}
 
inline void mainwork()
{
    ans[0]=0;sum=n;
    for(int i=1;i<=n;i++)
    if(ina[i])
    {
        q[1]=i;
        dfs(2);
    }
}
 
inline void print()
{
 	long long sum=0;
	for(int i=1;i<=n;i++)
		sum+=ans[i];  
	printf("%lld\n",sum);
}
 
int main()
{
    mi[0]=1;
    for(int i=1;i<=30;i++)
        mi[i]=mi[i-1]*2;
    int t;
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        prework();
        mainwork();
        print();
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值