题目传送门:http://codeforces.com/contest/732/problem/E
这题的费用流做法很显然吧?
但我们可以做得更优:
将插座排序后从小到大进行处理,枚举使用多少次转换器
仔细想一想:如果此时扫描到有未匹配的电脑那么直接匹配不会使答案变劣
于是就这么贪心一下就行啦
#include<bits/stdc++.h> #define LL long long using namespace std; const int N = 200000+9; const double EPS = 1e-8; struct Socks{ int id,val; inline bool operator < (const Socks &tmp) const { return val < tmp.val; } }s[N]; int p[N],n,m,nxt[N],num[N],v1[N],v2[N]; map<int,int> head; inline int read(){ char c=getchar(); int ret=0,f=1; while (c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();} while (c<='9'&&c>='0') {ret=ret*10+c-'0';c=getchar();} return ret*f; } inline void insert(int w, int v) { static int T = 0; nxt[++T] = head[w]; num[T] = v; head[w] = T; } int main(){ n = read(); m = read(); for (int i=1;i<=n;i++) p[i] = read(); for (int i=1;i<=m;i++) s[i].val = read(), s[i].id = i; for (int i=1;i<=n;i++) insert(p[i],i); sort(s+1,s+1+m); for (int i=1;i<=m;i++) { for (int w=0,cur=s[i].val;;cur=(int)(ceil((double)cur/2)+EPS),w++) { if (head[cur]) { v1[s[i].id] = w; v2[num[head[cur]]] = s[i].id; head[cur] = nxt[head[cur]]; break; } if (cur == 1) break; } } int vout1 = 0, vout2 = 0; for (int i=1;i<=m;i++) vout1 += v1[i]; for (int i=1;i<=n;i++) vout2 += (v2[i] > 0); cout<<vout2<<' '<<vout1<<endl; for (int i=1;i<=m;i++) printf("%d ",v1[i]); cout<<endl; for (int i=1;i<=n;i++) printf("%d ",v2[i]); return 0; }