题目有点长,就直接放链接了 https://www.luogu.org/problem/show?pid=1314
直接二分W值 处理前缀和和数量就可以了
注意要开long long
#include<bits/stdc++.h> using namespace std; #define maxn 200005 #define ll long long int n,m; ll S; int w[maxn],v[maxn],l[maxn],r[maxn]; ll sum[maxn],cnt[maxn]; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } ll judge(int W){ memset(sum,0,sizeof sum); memset(cnt,0,sizeof cnt); for(int i=1;i<=n;i++){ sum[i]+=sum[i-1]; cnt[i]+=cnt[i-1]; if(w[i]>=W){ sum[i]+=v[i]; cnt[i]++; } } ll tmp=0; for(int i=1;i<=m;i++){ tmp+=(cnt[r[i]]-cnt[l[i]-1])*(sum[r[i]]-sum[l[i]-1]); } return tmp; } int main(){ scanf("%d%d%lld",&n,&m,&S); int mx=0; for(int i=1;i<=n;i++){ scanf("%d%d",&w[i],&v[i]); mx=max(w[i],mx); } for(int i=1;i<=m;i++){ scanf("%d%d",&l[i],&r[i]); } int l=0,r=mx+1; ll ans=(1LL<<60); while(l<=r){ int mid=(l+r)>>1; ll t=judge(mid); ans=min(ans,abs(S-t)); if(t<S)r=mid-1;//注意二分的取值 else l=mid+1; } printf("%lld",ans); return 0; }