关于题意的分析就转一下大牛的了~~
不过这道题真的就是在考读题,其他都没什么好做的= =!!!不过我太菜了,A了快一个小时才A出来,郁闷啊
题意:你给第i个人喝普通可乐他能给你Pi个盖子,给他中奖可乐他能给你Qi个盖子。中奖可乐用M个盖子可以换一个,盖子可以先借用再去换可乐。问:最多能获得盖子数。
思路:按Qi-Pi差值排序。临界点是Qi-Pi=M,这时候换不换中奖可乐,最后得到的盖子是一样的。所以二分下临界点的位置。然后答案就是临界点之前的Pi求和+临界点之后Qi-M求和。
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
struct person{
int pi,qi;
int cha;
bool operator < (person a)const{
return a.cha>cha;
}
bool operator <(int a)const{
return a<cha;
}
}per[100005];
int sumpi[100005],sumqi[100005];
bool cmp(person a,person b){
return a.cha<b.cha;
}
int main(){
int m,n;
while(scanf("%d%d",&m,&n)!=EOF){
memset(sumpi,0,sizeof(sumpi));
memset(sumqi,0,sizeof(sumqi));
for(int i=0;i<m;i++){
scanf("%d%d",&per[i].pi,&per[i].qi);
per[i].cha=per[i].qi-per[i].pi;
}
sort(per,per+m,cmp);
int M;
sumpi[0]=per[0].pi;
sumqi[0]=per[0].qi;
for(int i=1;i<m;i++){
sumpi[i]=sumpi[i-1]+per[i].pi;
sumqi[i]=sumqi[i-1]+per[i].qi;
}
int ans=-1;
for(int i=0;i<n;i++){
scanf("%d",&M);
//int l=0,r=m;
/*
int mm=(l+r)/2;
if(per[mm].cha>M) r=mm-1;典型的彩笔敲的二分,大错特错!!
if(per[mm].cha<M) l=mm+1;
if(per[mm].cha==M){
ans=mm;
break;
}
}
if(ans==-1) printf("error\n");
else printf("%d\n",sumpi[ans]+(sumqi[m]-sumqi[ans]-m*(m-ans)));//注意临界值!!!很重要
*/
//ans=lower_bound(per,per+m,M)-per;
int l = 0, r = m, ans = -1;
while (l <= r)
{
int mm = (l + r) / 2;
if (per[mm].cha < M) l = mm + 1;//这个就当二分模板把
else
{
ans = mm; r = mm - 1;
}
}
if(ans==-1) printf("%d\n",sumpi[m-1]);
else printf("%d\n",sumpi[ans-1]+(sumqi[m-1]-sumqi[ans-1]-M*(m-ans)));
}
}
}