BZOJ2465: [中山市选2009]小球

看错两次题目
第一次以为是01背包
第二次以为是每个杯子一个询问
日狗..
一堆网络流过得。。并不是很理解QWQ
其实直接二分就好了啦

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline int min(int a,int b)
{return a>b?b:a;
}
char c;
inline void read(int &a)
{
   a=0;do c=getchar();while(c<'0'||c>'9');
   while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}

int F[301][301];
int Val[301];
struct Query
{
   int id,MaxV,MaxQ,ans1,ans2;
   inline friend bool operator <(Query a,Query b)
   {return a.id<b.id;} 
}Q[201];


inline bool cmp(Query a,Query b)
{
  return a.MaxQ>b.MaxQ;
}
int Pre[301];
int main()
{
    int n,m;
    int i,j=0;
    while(true)
    {
    memset(F,0,sizeof(F));
    read(n),read(m);
    if(n==0)break;
    for(i=1;i<=n;i++)
       read(Val[i]);
    sort(Val+1,Val+1+n);
    for(int i=1;i<=n;i++)Pre[i]=Pre[i-1]+Val[i];
    Val[n+1]=328787837;
    for(i=1;i<=m;i++)
         read(Q[i].MaxV),read(Q[i].MaxQ),Q[i].id=i; 
         sort(Q+1,Q+1+m,cmp);
    int Cur=n+1;  
    int A1=0,A2=0;
    for(i=1;i<=m;i++)
    {

         int as,l=0,r=n+1,mid;
         while(l<=r)
         {
            mid=l+r>>1;
            if(Val[mid]>Q[i].MaxQ)r=mid-1;
            else l=mid+1,as=mid;
         }
         Q[i].ans1=min(min(as,Q[i].MaxV),Cur-1);
         Q[i].ans2=Pre[min(as,Cur-1)]-Pre[min(as,Cur-1)-Q[i].ans1];
         Cur=min(as,Cur-1)-Q[i].ans1+1;
         A1+=Q[i].ans1;
         A2+=Q[i].ans2;
    }
       printf("%d %d\n",A1,A2);
    }

   return 0;
} 

你可能感兴趣的:(BZOJ2465: [中山市选2009]小球)