显然可以二分参数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 }