P1314 聪明的质监员(前缀和+二分)

P1314 聪明的质监员

显然可以二分参数W

统计Y用下前缀和即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cctype>
 5 #include<algorithm>
 6 #include<cmath>
 7 #define re register
 8 using namespace std;
 9 typedef long long ll;
10 void read(int &x){
11     char c=getchar();x=0;
12     while(!isdigit(c)) c=getchar();
13     while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
14 }
15 ll min(ll a,ll b){return a<b?a:b;}
16 #define N 200002
17 int n,m,w[N],v[N],tl[N],tr[N],c[N];
18 ll s,sum1[N],sum2[N],ans=1e17;
19 ll check(int lim){
20     for(re int i=1;i<=n;++i){
21         if(w[i]<lim){
22             sum1[i]=sum1[i-1];
23             sum2[i]=sum2[i-1];
24         }else{
25             sum1[i]=sum1[i-1]+v[i];//存权值和
26             sum2[i]=sum2[i-1]+1;//存个数
27         }
28     }ll res=0;
29     for(re int i=1;i<=m;++i){
30         ll r1=sum1[tr[i]]-sum1[tl[i]-1];
31         ll r2=sum2[tr[i]]-sum2[tl[i]-1];
32         res+=r1*r2;//累加Y值
33     }ans=min(ans,abs(res-s));
34     return res;
35 }
36 int main(){
37     read(n);read(m);scanf("%lld",&s);
38     for(re int i=1;i<=n;++i) read(w[i]),read(v[i]),c[i]=w[i];
39     for(re int i=1;i<=m;++i) read(tl[i]),read(tr[i]);
40     sort(c+1,c+n+1);//重量值从小到大排序,用于二分
41     int l=1,r=n;
42     while(l<r){
43         int mid=l+((r-l)>>1);
44         if(check(c[mid])>s) l=mid+1;//二分离s更近
45         else r=mid;
46     }printf("%lld",ans);
47     return 0;
48 }
View Code
原文地址:https://www.cnblogs.com/kafuuchino/p/9877775.html