bzoj 3689 异或之

来源:互联网 发布:java订单管理系统源码 编辑:程序博客网 时间:2024/05/16 19:00

二分答案+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 4000010using 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_JUDGEfreopen("data.in","r",stdin); //freopen("data.out","w",stdout);#endifscanf("%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;}


0 0