洛谷P1314 [NOIP 2011 提高组] 聪明的质监员 题解

洛谷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;
}
posted @ 2025-02-07 19:16  2789617221guo  阅读(29)  评论(0)    收藏  举报