首先根据题意如果想暴力的话,应该是枚举标准w,然后观察所得y的特点,不难发现随着w的增大,y 是逐渐减小的,满足递减的规律,不难想到可以用二分来做,为了防止超时,可以用前缀和。
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const ll maxn=200100;
ll n,m,s,h[maxn],t[maxn],v[maxn],w[maxn],num[maxn],sum[maxn];
ll l=maxn,r,y,ans,ans1,ans2,b;
ll f(ll x)
{
y=0;num[0]=0;sum[0]=0;
for(int i=1;i<=n;i++)
{
if(w[i]>=x)
{
num[i]=num[i-1]+1;
sum[i]=sum[i-1]+v[i];
}
else
{
num[i]=num[i-1];
sum[i]=sum[i-1];
}
}
for(int i=1;i<=m;i++)
y+=(num[t[i]]-num[h[i]-1])*(sum[t[i]]-sum[h[i]-1]);
if(y>s) return 1;
if(y<s) return 0;
if(y==s)
{
b=1;cout<<0;return 0;
}
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&s);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&w[i],&v[i]);
l=min(w[i],l);r=max(r,w[i]);
}
for(int i=1;i<=m;i++)
scanf("%lld%lld",&h[i],&t[i]);
while(l<=r)
{
ll mid=(l+r)/2;
if(f(mid))
{
ans1=y;l=mid+1;
}
else
{
if(b) return 0;
ans2=y;r=mid-1;
}
}
ans=min(ans1-s,s-ans2);
cout<<ans;
return 0;
}