洛谷P1314 [NOIP 2011 提高组] 聪明的质监员 题解
题目
题目传送门。
题解
思路
这题可以使用前缀和优化+二分答案法求解。
首先读入\(m\)组区间,左右端点分别存放到数组\(left_i\)和\(right_i\)中。二分查找\(W\),左边界\(l\)和右边界\(r\)初始值分别为0和1000001,每次调用一个函数\(check(int\ x)\)用于判断当\(W=x\)时是否满足需求。
\(check\)细节:求出\(y\)的值后,返回\(y>s\),并更新最小值。
当\(y>s\)时,意味着\(W\)小了(具体看公式),所以提高\(W\)的取值范围,否则减小\(W\)的取值范围。
最后输出一直在比较大小的答案值\(ans\)就可以啦。
代码
#include<bits/stdc++.h>
#define endl '\n'
#define INF 0x7fffffff
#define EPS 1e-8
using namespace std;
long long n,m,s,ans=LLONG_MAX,W2,sum,s1[200005],s2[200005],w[200005],v[200005],l[200005],r[200005];
void check(int W){for(int i=1;i<=n;i++){s1[i]=s1[i-1]+(w[i]>=W);s2[i]=s2[i-1]+((w[i]>=W)?v[i]:0);}sum=0;for(int i=1;i<=m;i++){sum+=(s1[r[i]]-s1[l[i]-1])*(s2[r[i]]-s2[l[i]-1]);}ans=min(ans,abs(s-sum));
}
int main(){cin>>n>>m>>s;long long mxw=-1;for(int i=1;i<=n;i++){cin>>w[i]>>v[i];mxw=max(mxw,w[i]);}for(int i=1;i<=m;i++){cin>>l[i]>>r[i];}long long left=0,right=mxw+1;while(left<=right){long long mid=(left+right)/2;check(mid);sum>s?left=mid+1:right=mid-1;}cout<<ans<<endl;return 0;
}