题目大意
对于一个区间 ,计算矿石在这个区间上的检验值 :
记检验结果为 ,对于给定的 ,求 的最小值。
分析
注意到 是关于 的递减函数,对 在 上进行二分。
const ll MN = 2e5 + 10;
ll vv[MN], ww[MN], li[MN], ri[MN], f1[MN], f2[MN];
ll n, m, s;
int main() {
n = rr(), m = rr(), s = rr();
ll minw = 0x3f3f3f3f, maxw = 0;
f1[0] = f2[0] = 0;
for (ll i = 1; i <= n; i++) {
ww[i] = rr(), vv[i] = rr();
maxw = max(ww[i], maxw);
minw = min(ww[i], minw);
}
for (ll i = 1; i <= m; i++) {
li[i] = rr(), ri[i] = rr();
}
ll l = minw, r = maxw + 1;
while (l < r) {
int mid = (l + r) >> 1;
if (sum(mid) <= s)
r = mid;
else
l = mid + 1;
}
ll rst = min(sum(l - 1) - s, s - sum(l));
printf("%lld", rst);
return 0;
}
区间求和可以用前缀和优化。
ll f1[MN], f2[MN];
ll sum(ll w) {
for (ll i = 1; i <= n; i++) {
ll f = ww[i] >= w;
f1[i] = f1[i - 1] + f;
f2[i] = f2[i - 1] + f * vv[i];
}
ll sum = 0;
for (ll k = 1; k <= m; k++) {
ll l = li[k], r = ri[k];
sum += (f1[r] - f1[l - 1]) * (f2[r] - f2[l - 1]);
}
return sum;
}