泥豪!我是2789617221guo!欢迎来|

2789617221guo

园龄:1个月粉丝:2关注:2

2025-02-07 19:16阅读: 5评论: 0推荐: 0

洛谷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;
}

本文作者:2789617221guo

本文链接:https://www.cnblogs.com/2789617221guo/p/18703134

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   2789617221guo  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起