letgogogogo

导航

P1314 [NOIP2011 提高组] 聪明的质监员

P1314 [NOIP2011 提高组] 聪明的质监员

# [NOIP2011 提高组] 聪明的质监员

题目描述

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

  1. 给定 个区间
  2. 选出一个参数
  3. 对于一个区间 ,计算矿石在这个区间上的检验值

其中 为矿石编号。

这批矿产的检验结果 为各个区间的检验值之和。即:

若这批矿产的检验结果与所给标准值 相差太多,就需要再去检验另一批矿产。小T 不想费时间去检验另一批矿产,所以他想通过调整参数 的值,让检验结果尽可能的靠近标准值 ,即使得 最小。请你帮忙求出这个最小值。

输入格式

第一行包含三个整数 ,分别表示矿石的个数、区间的个数和标准值。

接下来的 行,每行两个整数,中间用空格隔开,第 行表示 号矿石的重量 和价值

接下来的 行,表示区间,每行两个整数,中间用空格隔开,第 行表示区间 的两个端点 。注意:不同区间可能重合或相互重叠。

输出格式

一个整数,表示所求的最小值。

样例 #1

样例输入 #1

5 3 15 
1 5 
2 5 
3 5 
4 5 
5 5 
1 5 
2 4 
3 3

样例输出 #1

10

提示

【输入输出样例说明】

的时候,三个区间上检验值分别为 ,这批矿产的检验结果为 ,此时与标准值 相差最小为

【数据范围】

对于 的数据,有

对于 的数据,有

对于 的数据,有

对于 的数据,有

对于 的数据,有

题解

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=200010;
struct re{
    ll left,right;
}section[maxn];
ll n,m,s,v[maxn],w[maxn],i,j,sum1[maxn],sum2[maxn];
ll now;
ll ab(ll c)
{
    return c>0 ? c : -c ;
}
void look_up(ll l,ll r)
{
    if(l==r)return;
    ll mid=(l+r)/2;
    memset(sum1,0,sizeof(sum1));
    memset(sum2,0,sizeof(sum2));
    for(i=1;i<=n;i++)
    {
        sum1[i]=sum1[i-1];
        sum2[i]=sum2[i-1];
        if(w[i]>=mid)
        {
            sum1[i]++;
            sum2[i]+=v[i];
        }
    }
    ll Y=0;
    for(i=1;i<=m;i++)
    {
        Y+=(sum1[ section[i].right ]-sum1[ section[i].left-1 ])*(sum2[ section[i].right ]-sum2[ section[i].left-1 ]);
    }
    if(ab(s-Y)<ab(s-now))now=Y;
    if(s>Y)look_up(l,mid);
    if(s==Y)
    {
        now=s;
        return;
    }
    if(s<Y)look_up(mid+1,r);
}
int main()
{
    scanf("%lld%lld%lld",&n,&m,&s);
    for(i=1;i<=n;i++)scanf("%lld%lld",&w[i],&v[i]);
    for(i=1;i<=m;i++)scanf("%lld%lld",§ion[i].left,§ion[i].right);
    look_up(1,100000);
    printf("%lld",ab(s-now));
    return 0;
}

 

posted on 2024-11-18 22:58  总在北极扫雪  阅读(8)  评论(0编辑  收藏  举报