思路分析:
观察式子可以发现要满足最小,即
与
越接近越好。
在观察检验值的公式可以发现若越大,满足
和
将减小,导致检验值的减小。所以我们可以发现当
时我们要增大
,当
时减小
,这才能使
与
不断接近。
其中检验值的计算可以通过前缀和优化。代表前
个中满足条件的元素个数,
同理。
Code:
#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
#pragma GCC optimize(3)
typedef long long LL;
#define MaxN 200010
#define INF 1e18
LL w[MaxN],v[MaxN],n,m,s;
LL sums[MaxN],muls[MaxN],maps[MaxN][2],A,B;
bool check(LL x){
for(int i=1; i<=n; i++)
if( w[i] >= x ){
sums[i]=sums[i-1]+1;
muls[i]=muls[i-1]+v[i];
}
else{
sums[i]=sums[i-1];
muls[i]=muls[i-1];
}
A=0;
for(int i=1; i<=m; i++)
A+=(sums[maps[i][1]]-sums[maps[i][0]-1])*(muls[maps[i][1]]-muls[maps[i][0]-1]);
B=abs(s-A);
return A > s;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>s;
for(int i=1; i<=n; i++) cin>>w[i]>>v[i];
for(int i=1; i<=m; i++) cin>>maps[i][0]>>maps[i][1];//0左1右
LL _left=0,_right=1e9,ans=INF;
while( _left <= _right ){
LL mid=(_left+_right)>>1;
if( check(mid) ) _left=mid+1;
else _right=mid-1;
ans=min(ans,B);
}
cout<<ans;
return 0;
} 
京公网安备 11010502036488号