题目描述 https://www.luogu.org/problemnew/show/P1314
找合适的w使差值最小,二分
直接搜的话会超时,要用前缀和
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int l=2147483647,r=-1,n,m;
int v[N],w[N],b[N],t[N];
ll s,ans=1e115+5,sum,sv[N],sn[N];
bool jud(int x)
{
ll tmp=0;
memset(sv,0,sizeof(sv));
memset(sn,0,sizeof(sn));
for(int i=1;i<=n;i++)
{
if(w[i]>=x) sv[i]=sv[i-1]+v[i],sn[i]=sn[i-1]+1;
else sv[i]=sv[i-1],sn[i]=sn[i-1];
}
for(int i=1;i<=m;i++)
tmp=tmp+(sn[t[i]]-sn[b[i]-1])*(sv[t[i]]-sv[b[i]-1]);
sum=abs(tmp-s);
if(tmp>s) return 1;
else return 0;
}
int main()
{
scanf("%d%d%lld",&n,&m,&s);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&w[i],&v[i]);
l=min(l,w[i]),r=max(r,w[i]);
}
for(int i=1;i<=m;i++) scanf("%d%d",&b[i],&t[i]);
l-=1,r+=2;
while(l<=r)
{
int mid=(l+r)/2;
if(jud(mid)) l=mid+1;
else r=mid-1;
if(sum<ans) ans=sum;
}
printf("%lld",ans);
return 0;
}