zoukankan      html  css  js  c++  java
  • [NOIP2011提高组]聪明的质监员

    题目描述﹡﹡﹡

    小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有n 个矿石,从1
    到n 逐一编号,每个矿石都有自己的重量wi 以及价值vi。检验矿产的流程是:
    1、给定m 个区间[Li,Ri];
    2、选出一个参数W;
    3、对于一个区间[Li,Ri],计算矿石在这个区间上的检验值Yi :这个区间上所有重量大于等于W的矿石数目与它们的质量和的乘积。
    这批矿产的检验结果Y 为各个区间的检验值之和。
    若这批矿产的检验结果与所给标准值S 相差太多,就需要再去检验另一批矿产。小T
    不想费时间去检验另一批矿产,所以他想通过调整参数W 的值,让检验结果尽可能的靠近
    标准值S,即使得S-Y 的绝对值最小。请你帮忙求出这个最小值。

    【输入输出样例说明】
    当 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≤106,0 < S≤1012,1≤Li≤Ri≤n。

    输入格式

    第一行包含三个整数 n,m,S,分别表示矿石的个数、区间的个数和标准值。
    接下来的 n 行,每行2 个整数,中间用空格隔开,第i+1 行表示i 号矿石的重量wi 和价
    值vi 。
    接下来的 m 行,表示区间,每行2 个整数,中间用空格隔开,第i+n+1 行表示区间[Li,
    Ri]的两个端点Li 和Ri。注意:不同区间可能重合或相互重叠。

    输出格式

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

    题目本身并不难,只是在3个小时内想出解法而且还要做其他的题,确实很困难。

    本题要小心数据范围!

     1 #include<iostream>
     2 //#include<fstream> 
     3 using namespace std;
     4 //ifstream scanf("cin.in");
     5 //ofstream cout("cout.out"); 
     6 
     7 
     8 int a[200001],b[200001],x[200001],y[200001],m,n;long long z=0,s,sumv[200001]={0},sums[200001]={0};
     9 int mid;
    10 bool p=1; 
    11 
    12 bool check(){
    13      int i;long long total=0;
    14      
    15      for(i=1;i<=n;++i)
    16      {
    17       sumv[i]=sumv[i-1];
    18       sums[i]=sums[i-1];                
    19       if(a[i]>=mid) {sumv[i]+=b[i];sums[i]++;}                
    20                       } 
    21       
    22      for(i=1;i<=m;i++)
    23      total+=(sums[y[i]]-sums[x[i]-1])*(sumv[y[i]]-sumv[x[i]-1]); 
    24      
    25      if(p==1) {z=abs(total-s);p=0;if(total<s) return 1;return 0;}
    26      if(abs(total-s)<z&&total<s) {z=abs(total-s);return 1;}
    27      if(abs(total-s)<z&&total>s) {z=abs(total-s);return 0;}
    28      if(total<s) return 1;
    29      return 0;
    30      }
    31 
    32 int main()
    33 {
    34     int i,j,k,left=0,right=0;
    35     scanf("%d%d%I64d",&n,&m,&s); 
    36   //  cin>>n>>m>>s;
    37     for(i=1;i<=n;i++)
    38     {scanf("%d%d",&a[i],&b[i]);if(a[i]>right) right=a[i];}//cin>>a[i]>>b[i];
    39     
    40     for(i=1;i<=m;i++)
    41     scanf("%d%d",&x[i],&y[i]);//cin>>x[i]>>y[i];
    42     
    43     mid=(left+right)/2;
    44     while(left<=right)
    45     {
    46       if(check())  
    47       right=mid-1;
    48       else left=mid+1;  
    49       mid=(left+right)/2;         
    50                      }
    51     
    52     cout<<z<<endl;     
    53     return 0;
    54     
    55     }
  • 相关阅读:
    [PHP] class_exists类不存在时会调用__autoload函数
    [Redis] Redis的消息机制- 发布订阅
    [发电] 现在正式入驻爱发电平台
    [MySQL] PHP IP登录限制的实现
    [Redis] 哈希表的Rehash机制
    [Redis] redis的hash类型底层结构哈希表
    [Linux] ls命令的几个常用参数实现按时间/文件大小排序
    [Go] 在gin框架gorm下查询一对多的数据
    [Redis] list底层的数据结构
    [GO]go redis实现滑动窗口限流-redis版
  • 原文地址:https://www.cnblogs.com/noip/p/2582057.html
Copyright © 2011-2022 走看看