zoukankan      html  css  js  c++  java
  • 【NOIP2011】 聪明的质监员

    小 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。

    题解:

         我居然写了主席树!然后san分被卡=-=

    ----自作孽不可活。

      显然这是个随选定W值增加Y值呈不上升趋势的函数。

      然后求W-Y函数中一个最接近S的值,二分W。

      

     1 #include<cstdio>
     2 #include<iostream>
     3 using namespace std;
     4 typedef long long ll;
     5 const int N=200200;
     6 int n,m;
     7 int w[N],v[N];
     8 ll S;
     9 struct Q{
    10     int l,r;
    11 }query[N];
    12 int cnt[N];
    13 ll sum[N];
    14 int mar;
    15 inline ll solve(int val){
    16     cnt[0]=0,sum[0]=0;
    17     for(int i=1;i<=n;i++)
    18         cnt[i]=cnt[i-1]+(w[i]>=val),sum[i]=sum[i-1]+v[i]*(w[i]>=val);
    19     ll ans=0;
    20     for(int i=1,l,r;i<=m;i++){
    21         l=query[i].l,r=query[i].r;
    22         ans+=(cnt[r]-cnt[l-1])*(sum[r]-sum[l-1]);
    23     }
    24     return ans;
    25 }
    26 int main(){
    27     scanf("%d%d%lld",&n,&m,&S);
    28     for(int i=1;i<=n;i++)
    29         scanf("%d%d",w+i,v+i),mar=mar>w[i]?mar:w[i];
    30     for(int i=1;i<=m;i++)
    31         scanf("%d%d",&query[i].l,&query[i].r);
    32     int l=0,r=mar+1;
    33     while(l<r-1){
    34         int mid=l+r>>1;
    35         ll tot=solve(mid);
    36         if(tot<=S){
    37             r=mid;
    38         }
    39         else{
    40             l=mid;
    41         }
    42     }
    43     printf("%lld
    ",min(abs(solve(l)-S),abs(solve(r)-S)));
    44 }
  • 相关阅读:
    mysql 中只能使用 localhost 登录,用ip不能登陆
    在springboot 和 mybatis 项目中想要显示sql 语句进行调试
    从一张表数据导入到另一张表
    mysql 中 delete 子查询的限制
    配置eureka 老是报错connected time out 或者 refused connected
    Linux-TCP 出现 RST 的几种情况
    MySQL-优化之 index merge(索引合并)
    Python-Mac 安装 PyQt4
    PHP-PHP-FPM的max_children一些误区
    Linux-磁盘及网络IO工作方式解析
  • 原文地址:https://www.cnblogs.com/Troywar/p/7286050.html
Copyright © 2011-2022 走看看