贪心,优先队列。
将$s$按照从小到大的顺序扔进优先队列。从小的开始与电脑配对,如果找不到合适的电脑,那么再变小一次,直到找到与之配对的电脑或者作废。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<ctime> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-10; void File() { freopen("D:\in.txt","r",stdin); freopen("D:\out.txt","w",stdout); } template <class T> inline void read(T &x) { char c = getchar(); x = 0; while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } } int n,m; int p[200010],s[200010],cnt[200010]; int h[200010],nx[200010]; int c,u; int a[200010],b[200010],r[200010]; struct X { int s,id; X(int S,int ID) { s=S; id=ID; } bool operator < (const X &a) const { return s>a.s; } }; priority_queue<X>q; int Z(int x) { int L=1,R=n,res=-1; while(L<=R) { int mid=(L+R)/2; if(r[mid]>x) R=mid-1; else if(r[mid]==x) R=mid-1,res=mid; else L=mid+1; } return res; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&p[i]); r[i]=p[i]; } sort(r+1,r+1+n); memset(h,-1,sizeof h); for(int i=1;i<=n;i++) { int pp=Z(p[i]); nx[i]=h[pp], h[pp]=i; } for(int i=1;i<=m;i++) { scanf("%d",&s[i]); q.push(X(s[i],i)); } while(!q.empty()) { X top = q.top(); q.pop(); while(1) { int pp=Z(top.s); if(top.s==1&&pp==-1) break; if(top.s==1&&pp!=-1&&h[pp]==-1) break; if(pp!=-1&&h[pp]!=-1) { c++; u=u+cnt[top.id]; a[top.id]=cnt[top.id]; b[h[pp]]=top.id; h[pp]=nx[h[pp]]; break; } else { if(top.s%2==0) top.s=top.s/2; else top.s=top.s/2+1; cnt[top.id]++; } } } printf("%d %d ",c,u); for(int i=1;i<=m;i++) printf("%d ",a[i]); cout<<endl; for(int i=1;i<=n;i++) printf("%d ",b[i]); cout<<endl; return 0; }