原题: ZOJ 3676 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3676
题意:给每个朋友一瓶可乐,可乐有普通和高级两种,每个朋友只能喝一瓶可乐,喝普通可乐的朋友会给你P个瓶盖,喝高级可乐的朋友会给你Q个瓶盖。问最多能得到多少个瓶盖。瓶盖可以借。
解法:因为瓶盖可以借任意多个,所以按Q-P排序即可,二分临界点Q-P=0的点,即Q-P<m的让他和普通可乐,Q-P>m的喝高级可乐,Q-P=m的无所谓喝什么。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> using namespace std; #define N 100007 struct node { int P,Q; int dif; }p[N]; int SP[N],SQ[N]; int cmp(node ka,node kb) { return ka.dif < kb.dif; } int main() { int n,m,k; int i,j; while(scanf("%d%d",&n,&m)!=EOF) { SP[0] = SQ[0] = 0; for(i=1;i<=n;i++) { scanf("%d%d",&p[i].P,&p[i].Q); p[i].dif = p[i].Q-p[i].P; } sort(p+1,p+n+1,cmp); for(i=1;i<=n;i++) { SP[i] = SP[i-1]+p[i].P; SQ[i] = SQ[i-1]+p[i].Q; } for(i=0;i<m;i++) { scanf("%d",&k); int low = 1; int high = n; int res = -1; while(low <= high) { int mid = (low+high)/2; if(p[mid].dif < k) low = mid + 1; else { res = mid; high = mid - 1; } } if(res == -1) //如果全小于k,则全喝普通的 printf("%d ",SP[n]); else printf("%d ",SP[res-1]+SQ[n]-SQ[res-1]-(n-res+1)*k); } } return 0; }