思路分析:
观察式子可以发现要满足最小,即
与
越接近越好。
在观察检验值的公式可以发现若越大,满足
和
将减小,导致检验值的减小。所以我们可以发现当
时我们要增大
,当
时减小
,这才能使
与
不断接近。
其中检验值的计算可以通过前缀和优化。代表前
个中满足条件的元素个数,
同理。
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; }