zoukankan      html  css  js  c++  java
  • NOIP 2011 聪明的质监员

    题目描述

    小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 的绝对值最小。请你帮忙求出这个最小值。

    输入输出格式

    输入格式:

    输入文件qc.in 。

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

    接下来的n 行,每行2个整数,中间用空格隔开,第i+1 行表示 i 号矿石的重量 wi 和价值vi。

    接下来的m 行,表示区间,每行2 个整数,中间用空格隔开,第i+n+1 行表示区间[Li,Ri]的两个端点Li 和Ri。注意:不同区间可能重合或相互重叠。

    输出格式:

    输出文件名为qc.out。

    输出只有一行,包含一个整数,表示所求的最小值。

    输入输出样例

    输入样例#1:
    5 3 15 
    1 5 
    2 5 
    3 5 
    4 5 
    5 5 
    1 5 
    2 4 
    3 3 
    输出样例#1:
    10
    

    说明

    【输入输出样例说明】

    当W 选4 的时候,三个区间上检验值分别为 20、5 、0 ,这批矿产的检验结果为 25,此

    时与标准值S 相差最小为10。

    【数据范围】

    对于10% 的数据,有 1 ≤n ,m≤10;

    对于30% 的数据,有 1 ≤n ,m≤500 ;

    对于50% 的数据,有 1 ≤n ,m≤5,000;

    对于70% 的数据,有 1 ≤n ,m≤10,000 ;

    对于100%的数据,有 1 ≤n ,m≤200,000,0 < wi, vi≤10^6,0 < S≤10^12,1 ≤Li ≤Ri ≤n 。

    Other:

      这道题一直65分///

      原因在于寻找W是漏了一个等于号...

      不能再犯!

    Solution:

      虽然题面奇奇怪怪,但是还能看出来是二分答案,然后用前缀和统计。

      代码敲得比较丑,注意数据较大,要开long long。

     1 #include<cstdio>
     2 #define LL long long
     3 #define Min(a,b) (a<b?a:b)
     4 #define Max(a,b) (a>b?a:b)
     5 #define MAXN 2000005
     6 #define INF (1ll<<60)
     7 using namespace std;
     8 LL S,ans=INF;
     9 int n,m;
    10 int l[MAXN],r[MAXN];
    11 int w[MAXN],v[MAXN];
    12 LL sum[MAXN],cnt[MAXN];
    13 inline LL read(){
    14     LL x=0,f=1;char ch=getchar();
    15     while(ch<'0'||ch>'9')if(ch=='-'){f=-1;ch=getchar();};
    16     while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=getchar();};
    17     return x*f;
    18 } 
    19 LL Abs(LL a){return a>0?a:-a;}
    20 LL pre(int W){
    21     LL tmp=0;
    22     for(int i=1;i<=n;i++){
    23         sum[i]=sum[i-1];cnt[i]=cnt[i-1];
    24         if(w[i]>=W){
    25             sum[i]+=v[i];cnt[i]++;
    26         }
    27     }
    28     for(int i=1;i<=m;i++){
    29         tmp+=(cnt[r[i]]-cnt[l[i]-1])*(sum[r[i]]-sum[l[i]-1]);
    30     }
    31     return tmp;
    32 }
    33 int main(){
    34     //freopen("qc.in","r",stdin);
    35     //freopen("qc.out","w",stdout);
    36     int Mx=0;
    37     n=read();m=read();S=read();
    38     for(int i=1;i<=n;i++){w[i]=read();v[i]=read();Mx=Max(Mx,w[i]);}
    39     for(int i=1;i<=m;i++){l[i]=read();r[i]=read();}
    40     int ll=0,rr=Mx+1;
    41     while(ll<=rr){
    42         int mid=(ll+rr)>>1;
    43         LL y=pre(mid);//y is the mid of price 
    44             //printf("y=%lld
    ",y);
    45             //printf("Abs=%d
    ",Abs(y-S));
    46         ans=Min(ans,Abs(y-S));
    47             //printf("ans=%lld
    ",ans);
    48         if(y<S) rr=mid-1;
    49         else ll=mid+1;
    50     }
    51     printf("%lld
    ",ans);
    52     return 0;
    53 }
  • 相关阅读:
    Server Tomcat v8.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
    用户画像——“打标签”
    python replace函数替换无效问题
    python向mysql插入数据一直报TypeError: must be real number,not str
    《亿级用户下的新浪微博平台架构》读后感
    【2-10】标准 2 维表问题
    【2-8】集合划分问题(给定要分成几个集合)
    【2-7】集合划分问题
    【2-6】排列的字典序问题
    【2-5】有重复元素的排列问题
  • 原文地址:https://www.cnblogs.com/drizzly/p/7611792.html
Copyright © 2011-2022 走看看