NOIP2011 聪明的质检员(二分答案)
题解
单调性是当s-y大于0时w越小答案越优,反过来也成立。
所以二分答案。
然后问题是Yi怎么求,最接用前缀和预处理就行了。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const int N=200010; 8 long long n,m,s,sumv[N],sumn[N],ar[N],al[N],w[N],v[N],y,sum,ans,minn,maxx,l,r,mid; 9 bool check(long long x){ 10 y=0;sum=0; 11 for(int i=1;i<=n;i++){ 12 sumv[i]=sumv[i-1]; 13 sumn[i]=sumn[i-1]; 14 if(w[i]>x)sumv[i]+=v[i],sumn[i]+=1; 15 } 16 for(int i=1;i<=m;i++){ 17 y+=(sumv[ar[i]]-sumv[al[i]-1])*(sumn[ar[i]]-sumn[al[i]-1]); 18 } 19 sum=(long long)abs(y-s); 20 if(y>s)return true; 21 else return false; 22 } 23 int main(){ 24 scanf("%lld%lld%lld",&n,&m,&s); 25 minn=999999999; 26 for(int i=1;i<=n;i++){ 27 scanf("%lld%lld",&w[i],&v[i]); 28 minn=min(minn,w[i]); 29 maxx=max(maxx,w[i]); 30 } 31 for(int i=1;i<=m;i++){ 32 scanf("%d%d",&al[i],&ar[i]); 33 } 34 l=minn-1; 35 r=maxx+2; 36 long long ans=19999999999999999; 37 while(l<=r){ 38 mid=(l+r)>>1; 39 if(check(mid))l=mid+1; 40 else r=mid-1; 41 if(sum<ans)ans=sum; 42 } 43 printf("%lld",ans); 44 return 0; 45 }