二分答案+trie判定。卡时过
之后看题解:
用堆维护每个数可以获得的最小答案,每次取出最小元素,查询它的比当前大的最小值,加入堆。就和dijstra求k短路差不多的思路。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define eps 1e-10
#define md
#define N 4000010
using namespace std;
int sz[N],ch[N][2],q[N];
int cnt=0,X,n,K,w=0;
int a[100010];
const int mxdep=30;
void insert(int &i,int dep,int dt)
{
if (!i) i=++cnt;
sz[i]++;
//printf("insert %d %d %d\n",i,dep,sz[i]);
if (dep<0) return;
int t=(dt>>dep)&1;
insert(ch[i][t],dep-1,dt);
}
int query(int i,int dep,int dt)
{
//printf("query %d %d %d\n",i,dep,sz[i]);
if (!i) return 0;
if (dep<0) return sz[i];
int t=(dt>>dep)&1; //printf("t %d %d %d %d\n",i,t,ch[i][0],ch[i][1]);
if (X&(1<<dep)) return sz[ch[i][t]]+query(ch[i][t^1],dep-1,dt);
else return query(ch[i][t],dep-1,dt);
}
bool ok(ll x)
{
ll ans=0; X=x;
for (int i=1;i<=n;i++) ans+=query(1,mxdep,a[i]);
ans-=n; ans>>=1;
//printf("%lld %lld\n",x,ans);
return ans>=K;
}
void get(int i,int dep,int dt,int now)
{
//printf("get %d [%d %d] %d %d %d\n",i,ch[i][0],ch[i][1],dep,dt,now);
if (!i) return;
if (dep<0)
{
for (int j=1;j<=sz[i];j++) q[++w]=now;
//printf("__ %d : %d\n",now,sz[i]);
return;
}
int t=(dt>>dep)&1;
get(ch[i][t],dep-1,dt,now); get(ch[i][t^1],dep-1,dt,now|(1<<dep));
}
void solve(int i,int dep,int dt,int l,int now)
{
//printf("solve %d %d %d\n",dt,dep,now);
if (!i) return;
if (dep<0)
{
for (int j=1;j<=sz[i];j++) q[++w]=now;
//printf("__? %d : %d\n",now,sz[i]);
return;
}
int t=(dt>>dep)&1;
if ((l>>dep)&1) { get(ch[i][t],dep-1,dt,now); solve(ch[i][t^1],dep-1,dt,l,now|(1<<dep));}
else solve(ch[i][t],dep-1,dt,l,now);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("data.in","r",stdin); //freopen("data.out","w",stdout);
#endif
scanf("%d%d",&n,&K);
int root=0;
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
insert(root,mxdep,a[i]);
}
ll l=0,r=2147483647;
while (l!=r)
{
ll mid=(l+r)>>1;
if (ok(mid)) r=mid; else l=mid+1;
}
//printf(":%lld\n",l);
K=(K<<1)+n; l--;
for (int i=1;i<=n;i++) solve(1,mxdep,a[i],l,0);
l++; while (w<=K) q[++w]=l;
sort(q+1,q+K+1);
for (int i=n+1;i<=K;i+=2) printf("%d ",q[i]); printf("\n");
return 0;
}