您的位置:首页 > 其它

洛谷 P1314 聪明的质监员

2016-10-22 21:32 197 查看
题目描述

小T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有 n 个矿石,从 1到n 逐一编号,每个矿石都有自己的重量 wi 以及价值vi 。检验矿产的流程是:

1 、给定m 个区间[Li,Ri];

2 、选出一个参数 W;

3 、对于一个区间[Li,Ri],计算矿石在这个区间上的检验值Yi:



这批矿产的检验结果Y 为各个区间的检验值之和。即:Y1+Y2…+Ym

若这批矿产的检验结果与所给标准值S 相差太多,就需要再去检验另一批矿产。小T

不想费时间去检验另一批矿产,所以他想通过调整参数W 的值,让检验结果尽可能的靠近

标准值S,即使得S-Y 的绝对值最小。请你帮忙求出这个最小值。

【题目分析】

二分。数组开小了WA了一次。

【代码】

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int w[200001],v[200001];
int l[200001],r[200001];
long long sumw[200001],sumv[200001];
int n,m;
long long s;
long long ok(int mid)
{
long long ret=0;
for (int i=1;i<=n;++i)
{
if (w[i]>=mid)
{
sumw[i]=sumw[i-1]+1;
sumv[i]=sumv[i-1]+v[i];
}
else sumw[i]=sumw[i-1],sumv[i]=sumv[i-1];
}
//  for (int i=1;i<=n;++i) printf("%lld ",sumw[i]); printf("\n");
//  for (int i=1;i<=n;++i) printf("%lld ",sumv[i]); printf("\n");
for (int i=1;i<=m;++i)
ret+=(sumw[r[i]]-sumw[l[i]-1])*(sumv[r[i]]-sumv[l[i]-1]);
return ret;
}
int main()
{
scanf("%d%d%lld",&n,&m,&s);
for (int i=1;i<=n;++i) scanf("%d%d",&w[i],&v[i]);
for (int i=1;i<=m;++i) scanf("%d%d",&l[i],&r[i]);
int ll=0,rr=1000000;
long long ansn=10000000000000000LL;
while (ll<rr)
{
int mid=(ll+rr)/2+1;
//      printf("now mid is %d\n",mid);
long long tmp=ok(mid)-s;
//      printf("now tmp is %lld\n",tmp);
ansn=min(ansn,abs(tmp));
if (tmp>0) ll=mid;
else if (tmp<0) rr=mid-1;
else {ansn=0; break;}
}
printf("%lld\n",ansn);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: