NOIP2015聪明的质检员[二分 | 预处理]

背景

NOIP2011 day2 第二题

描述

小T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有 n 个矿石,从 1到n 逐一编号,每个矿石都有自己的重量 wi 以及价值vi 。检验矿产的流程是: 
1 、给定m 个区间[Li ,Ri]; 
2 、选出一个参数 W; 
3 、对于一个区间[Li ,Ri],计算矿石在这个区间上的检验值Yi:
Yi=Σ1*Σvj,Σ的循环变量为j,这里j要满足j∈[Li,Ri]且wj≥W,这里j是矿石编号。

这批矿产的检验结果Y为各个区间的检验值之和。ΣYi,Σ的循环变量为i,1≤i≤m。

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

输入格式

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

输出格式

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

测试样例1

输入

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

输出

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 。

-------------------------------------------------------------------------------------------------------------------------------

二分

W增大,Y减小,可以二分

二分W,如果Y>S,在L到W-1二分;反之W+1到r,【过程中不停更新答案】

预处理

快速计算Y

对于一个W,扫一遍矿石计算有效矿石的数量前缀和 和 wi前缀和,每个区间一减就出来了

【注意long  long

#include <iostream>
#include<cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=200005;

int n,m;
int w[N],v[N],l[N],r[N];
int lw=0,rw=-1;
long long s,ans=1LL<<60;

long long sw[200005];    //s w
int sc[200005];            //s count
long long check(int ww){
    memset(sw,0,sizeof(sw));
    memset(sc,0,sizeof(sc));
    for(int i=1;i<=n;i++){    //pre
        if(w[i]>=ww){
            sw[i]=sw[i-1]+v[i];
            sc[i]=sc[i-1]+1;
        }else{
            sw[i]=sw[i-1];
            sc[i]=sc[i-1];
        }
    }
    long long y=0;
    for(int i=0;i<m;i++){
        y+=(sc[r[i]]-sc[l[i]-1])*(sw[r[i]]-sw[l[i]-1]);
    }
    return y;
}

int main() {
    scanf("%d%d%lld",&n,&m,&s);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&w[i],&v[i]);
        rw=max(rw,w[i]);
    }
    for(int i=0;i<m;i++)
        scanf("%d%d",&l[i],&r[i]);

    lw=0; rw++;
    while (lw<=rw){
        int mid=(lw+rw)>>1;
        long long y=check(mid);
        ans=min(ans,abs(y-s));    //update
        if(y<s) rw=mid-1;
        else lw=mid+1;
    }
    cout<<ans;
    return 0;
}
时间: 2024-11-05 02:20:14

NOIP2015聪明的质检员[二分 | 预处理]的相关文章

[NOIP 2011] 聪明的质检员

聪明的质检员 描述 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有n个矿石,从1到n逐一编号,每个矿石都有自己的重量wi以及价值vi.检验矿产的流程是:1.给定m个区间[Li,Ri]:2.选出一个参数W:3.对于一个区间[Li,Ri],计算矿石在这个区间上的 检验值$Y_i$:\[Y_i=(\sum_j {1}) \times(\sum_j v_j) ,j \in [L_i,R_i] \land \: w_i \geqslant W\] 其中 $j$ 为矿石编号 这批矿产的 

NOIP2011 聪明的质监员(二分)

由于我们并不清楚要求的W的值,但是我们知道W的值不超过矿石中价值最大的,如果W大于了矿石中价值最大的,那么Y的值为0,无法达到最优解. 因此,很容易就能想到在确定W的值要用二分的方法. 在分析这道题的时候,我们很容易知道Y的值是满足单调性的,当W的值越大,Y的值越小,因为W越大,能够选的矿石就越少. 所以我们把得到的Y值作为判断条件,如果Y比S小,就说明检验值了,而W取大了.每次更改W的同时给ans取最小值. 那么Y又应该怎么求出呢?题目中n,m最大有2*10^5,如果暴搜肯定超时,因此我们需要

P1314 聪明的质监员[二分答案]

题目描述 小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 nn 个矿石,从 11到nn 逐一编号,每个矿石都有自己的重量 w_i*w**i* 以及价值v_i*v**i* .检验矿产的流程是: 1 .给定mm个区间[L_i,R_i][Li,Ri]: 2 .选出一个参数WW: 3 .对于一个区间[L_i,R_i][Li,Ri],计算矿石在这个区间上的检验值Y_i*Y**i*: 这批矿产的检验结果YY 为各个区间的检验值之和.即:Y_1+Y_2...+Y_mY1+Y2...+*Y**

【NOIP2011】聪明的质检员

Description 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有n个矿石,从 1 到n逐一编号,每个矿石都有自己的重量wi以及价值vi.检验矿产的流程是: 1. 给定 m个区间[Li,Ri]: 2. 选出一个参数W: 3. 对于一个区间[Li,Ri],计算矿石在这个区间上的检验值Yi: 这批矿产的检验结果Y为各个区间的检验值之和.即: 若这批矿产的检验结果与所给标准值 S 相差太多,就需要再去检验另一批矿产.小 T 不想费时间去检验另一批矿产,所以他想通过调整参数 W

NOIP2011 聪明的质检员

描述 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有n个矿石,从1到n逐一编号,每个矿石都有自己的重量wi以及价值vi.检验矿产的流程是:1.给定m个区间[Li,Ri]:2.选出一个参数W:3.对于一个区间[Li,Ri],计算矿石在这个区间上的检验值Yi:Yi=(∑j1)∗(∑jvj) ,  j∈[Li,Ri]且wj≥WYi=(∑j1)∗(∑jvj) ,  j∈[Li,Ri]且wj≥Wj是矿石编号 这批矿产的检验结果Y 为各个区间的检验值之和.即:Y=∑i=1mYiY=∑i=

Vijos P1740聪明的质检员

题目 描述 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有n个矿石,从1到n逐一编号,每个矿石都有自己的重量wi以及价值vi.检验矿产的流程是:1.给定m个区间[Li,Ri]:2.选出一个参数W:3.对于一个区间[Li,Ri],计算矿石在这个区间上的检验值Yi:Yi = ∑1*∑vj,j∈[Li, Ri]且wj ≥ W,j是矿石编号这批矿产的检验结果Y 为各个区间的检验值之和.即:Y = ∑Yi,i ∈[1, m]若这批矿产的检验结果与所给标准值S相差太多,就需要再去检验另一

[题解]聪明的质检员

// 此博文为迁移而来,写于2015年7月14日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w6ft.html 1.题目 2.TAG NOIP提高组:二分答案:前缀和. 3.分析 首先题面一定要看懂,看清(上次我就是没有看懂).说白了,就是使W取一个最合适的值,使每一个所给区间内满足条件的矿石的数量乘上价值之和,最后计算总和使与S最近. 我们根据分值分布来分析算法: 1.30分算法:O(n^3),首先O(n)进行W

CODEVS1138聪明的质检员2011T5

题目描述 Description 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有n 个矿石,从1到n 逐一编号,每个矿石都有自己的重量wi 以及价值vi.检验矿产的流程是:见图 若这批矿产的检验结果与所给标准值S 相差太多,就需要再去检验另一批矿产.小T不想费时间去检验另一批矿产,所以他想通过调整参数W 的值,让检验结果尽可能的靠近标准值S,即使得S-Y 的绝对值最小.请你帮忙求出这个最小值. 思路: 题目描述...像个新定义的题...我真是...比较简单,可以看出w越大,y

洛谷 [P1314] 聪明的质检员(NOIP2011 D2T2)

一道二分答案加前缀和 题目中已经暗示的很明显了 "尽可能靠近" " 最小值" 本题的主要坑点在于 long long 的使用 abs函数不支持long long !!! #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; cons