zoukankan      html  css  js  c++  java
  • NOIP2011聪明的质监员题解

    631. [NOIP2011] 聪明的质监员

    ★★   输入文件:qc.in   输出文件:qc.out   简单对比
    时间限制:1 s   内存限制:128 MB

    【问题描述】 
    小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有n个矿石,从 1 到n逐一编号,每个矿石都有自己的重量wi以及价值vi。检验矿产的流程是: 
    1. 给定 m个区间[Li,Ri]; 
    2. 选出一个参数W; 
    3. 对于一个区间[Li,Ri],计算矿石在这个区间上的检验值Yi: 

    Yi=j1×jvj, j[Li,Ri] wjW,j是矿石编号

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

    Y=i=1mYi
    若这批矿产的

    检验结果

    与所给标准值 S 相差太多,就需要再去检验另一批矿产。小 T 不想费时间去检验另一批矿产,所以他想通过调整参数 W 的值,让

    检验结果

    尽可能的靠近标准值 S,即使得

    SY的绝对值最小。请你帮忙求出这个最小值。 

    【输入】 
    输入文件 qc.in。

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

    【输出】
    输出文件名为qc.out。
    输出只有一行,包含一个整数,表示所求的最小值。

    【输入输出样例】

    qc.in

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

    qc.out

    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。

      这道题一开始看到Σ还以为是数学题,果断跳过,然后发现自己错了……

      然后又以为是平衡树,然而昨天虽然刚打了平衡树却因为模板错误而没能学习区间操作,果断心虚。于是打了最暴力的暴力,强行水了5分。

      这道题最重要的有两点,第一,前缀和,第二,二分。

      先解释前缀和,这个很容易理解,就是sumv[i]为在i之前所有high不小于w的value的前缀和sumw[i]为在i之前高度不小于w的个数。

      然后就是二分,考试的时候以为是三分,之前没打过,打挂了。如果以abs(Y-S)为y轴,w为x轴,那么图像是一个绝对值函数,类似二次函数,很容易让人想到三分,然而值得注意的是Y本身是随w增大而递减的,而Y-S也是如此,我们就可以利用这个性质不断地二分w,使Y无限的去接近S,Y大于0就右移,反之左移,记得开long long。

      

     1 #include<iostream>
     2 #include<cstdlib>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<queue>
     6 #include<algorithm>
     7 #include<cmath>
     8 #include<map>
     9 using namespace std;
    10 int n,m;
    11 long long s;
    12 struct no{
    13     int va;
    14     int w;
    15 }node[2000005];
    16 struct qu{
    17     int li,ri;
    18 }que[2000004];
    19 long long sumw[2000005],sumv[2000005];
    20 long long check(int w){
    21     memset(sumv,0,sizeof(sumv));
    22     memset(sumw,0,sizeof(sumw));
    23     for(int i=1;i<=n;i++)
    24     {
    25         sumw[i]=sumw[i-1];
    26         sumv[i]=sumv[i-1];
    27         if(node[i].w>=w)
    28         {
    29             sumw[i]++;
    30             sumv[i]+=node[i].va;
    31         }
    32     }
    33     long long ans=0;
    34     for(int i=1;i<=m;i++)
    35     {
    36         ans+=(sumv[que[i].ri]-sumv[que[i].li-1])*(sumw[que[i].ri]-sumw[que[i].li-1]);
    37     }
    38     return ans;
    39 }
    40 long long minn(long long a,long long b){
    41     if(a>b)return b;
    42     return a;
    43 }
    44 long long llab(long long a){
    45     if(a<0)
    46     return -a;
    47     return a;
    48 }
    49 int main(){
    50     scanf("%d%d%lld",&n,&m,&s);
    51     int mx=0;
    52     for(int i=1;i<=n;i++)
    53     {
    54         scanf("%d%d",&node[i].w,&node[i].va);
    55         mx=max(mx,node[i].w);
    56     }
    57     for(int i=1;i<=m;i++)
    58         scanf("%d%d",&que[i].li,&que[i].ri);
    59     int li=1,ri=mx;
    60     long long ans=-1;
    61     while(li<=ri)
    62     {
    63         int mid=(li+ri)/2;
    64         long long x=check(mid);
    65         if(ans==-1)ans=llab(x-s);
    66         ans=minn(ans,llab(x-s));
    67         if(x>s)
    68             li=mid+1;
    69         else
    70             ri=mid-1;
    71     }
    72     printf("%lld
    ",ans);
    73     //while(1);
    74     return 0;
    75 }
    View Code
  • 相关阅读:
    读书笔记之理想设计的特征
    一些javascript 变量声明的 疑惑
    LINQ 使用方法
    Google MySQL tool releases
    读书笔记之设计的层次
    EF之数据库连接问题The specified named connection is either not found in the configuration, not intended to be used with the Ent
    转载 什么是闭包
    javascript面向对象起步
    Tips
    数据结构在游戏中的应用
  • 原文地址:https://www.cnblogs.com/liutianrui/p/7287257.html
Copyright © 2011-2022 走看看