从题中描述可以看出w和检验结果之间有一定关系:w越大检验结果越小,w越小检验结果越大。从而得到w的结果具有一个单调的性质。然后根据这个性质可以考虑二分w的做法。
在二分的过程中,如果Y>S那么w就得增大,如果Y<S那么w就得减小,如果Y==S那么直接退出就可以了。但我们最终的答案是需要取|S-Y|的最小值。
在计算Y的过程中也要注意不能直接暴力模拟,由于w的限制无法在一开始就对价格进行前缀和计算,但在计算Y的函数中w的值是确定的,在这时候可以使用前缀和将时间复杂度降低为:O(N)。
否则会超时。
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 200000+10;
ll rock[maxn][2];
ll qujian[maxn][2];
ll n, m, S;
ll jiany(ll mid) {
//构造价格的前缀和
ll price[maxn]={}, num[maxn]={}, y=0;
for (int i=1;i<=n;i++) {
price[i] = price[i-1];
num[i] = num[i-1];
if (rock[i][0]>=mid) {
price[i] += rock[i][1];
num[i] += 1;
}
}
//通过前缀和,遍历区间快速求结果
for (int i=1;i<=m;i++) {
y += (num[qujian[i][1]]-num[qujian[i][0]-1])*(price[qujian[i][1]]-price[qujian[i][0]-1]);
}
return y;
}
int main() {
scanf("%lld %lld %lld", &n, &m, &S);
for (int i=1;i<=n;i++) {
scanf("%lld %lld", &rock[i][0], &rock[i][1]);
}
for (int i=1;i<=m;i++) {
//保存测试的左右区间。
scanf("%lld %lld", &qujian[i][0], &qujian[i][1]);
}
ll l = 0, r = maxn, ans = 1e12;
// cout<<jiany(4)<<endl;
while (l<r) {
ll mid = (l+r)/2;
ll Y = jiany(mid);
// cout<<l<<" "<<r<<endl;
// cout<<"Y="<<Y<<endl;
if (Y>S) {
l = mid+1;
ans = min(ans, abs(S-Y));
}
if (Y<S) {
r = mid;
ans = min(ans, abs(S-Y));
}
if (Y==S) {
cout<<mid<<endl;
return 0;
}
}
cout<<ans;
return 0;
}

京公网安备 11010502036488号