二分答案+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; }