W越大,Y越小,所以可以二分W使Y接近S。
少用min、abs可以让思路更清晰。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
const int maxn = 200010;
int n, m, num[maxn];
int mw;
long long s, sum[maxn], tot;
struct node1{
int w, v;
} a[maxn];
struct node2{
int li, ri;
} b[maxn];
long long judge(int x){
memset(sum, 0, sizeof(sum));
memset(num, 0, sizeof(num));
for(int i = 1; i <= n; i++){
sum[i] = sum[i-1], num[i] = num[i-1];
if(a[i].w > x){
sum[i] += a[i].v;
num[i]++;
}
}
tot = 0;
for(int i = 1; i <= m; i++)
tot += (sum[b[i].ri] - sum[b[i].li-1])*(num[b[i].ri] - num[b[i].li-1]);
return tot;
}
int main(){
cin >> n >> m >> s;
for(int i = 1; i <= n; i++){
cin >> a[i].w >> a[i].v;
mw = max(mw, a[i].w);
}
for(int i = 1; i <= m; i++)
cin >> b[i].li >> b[i].ri;
long long ans = s;
int l = 0, r = mw + 1;
while(l < r){
int mid = (l+r) >> 1;
long long now = judge(mid);
if(now > s){
l = mid + 1;
if(ans > now - s) ans = now - s;
}
else if(now < s){
r = mid;
if(ans > s - now) ans = s - now;
}
else{
cout << "0" << endl;
return 0;
}
}
cout << ans << endl;
return 0;
}