如果s大于了y,那么就把y变大,w变小,反之变大。经典while(left<=right)
记得更新sum 和ans
#include<bits/stdc++.h>
using namespace std;
int n,m;
int ans;
long long s;long long sum;
long long y=0;
long long qz[900010],qzn[900010];
int w[900010],v[900010],l[900010],r[900010];
bool check(int mid)
{
y=0,sum=0;
memset(qz,0,sizeof(qz));
memset(qzn,0,sizeof(qzn));
for(int i=1;i<=n;i++)
{
if(w[i]>=mid)
{
qz[i]=qz[i-1]+v[i];
qzn[i]=qzn[i-1]+1;
}
else
{
qz[i]=qz[i-1];
qzn[i]=qzn[i-1];
}
}
for(int i=1;i<=m;i++)
{
y+=(qz[r[i]]-qz[l[i]-1])*(qzn[r[i]]-qzn[l[i]-1]);
}
sum=llabs(y-s);
if(y>s)
{
return true;
}
else
{
return false;
}
}
int main()
{
long long ans=0x3f3f3f3f3f3f3f3f;
scanf("%d%d%lld",&n,&m,&s);
int left=2147483647,right=-1;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&w[i],&v[i]);
left=min(left,w[i]);
right=max(right,w[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&l[i],&r[i]);
}
left=left-1;
right=right+2;
while(left<=right)
{
int mid=(left+right)/2;
if(check(mid))
{
left=mid+1;
}
else
{
right=mid-1;
}
if(sum<ans)
ans=sum;
}
printf("%lld",ans);
}
本题的前缀和虽然是相乘后的前缀和,但也差不多。