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

    题解:

      我们首先考虑到,对于一个W,因为区间是确定的,算出来的检验值Y,当W减小时,Y是不增的,因为对满足条件的矿石是不降的(wi>=W)。同理当W增大时,Y是不增的。这意味着Y是一个关于W的单调函数,于是我们就可以二分W值。若当前二分值为Wi,算出来的值为Yi,若S-Yi>0,我们就要设法减小Y值以更靠近S,于是我们就将左边界增大,若S-Yi<0,我们就要设法将Y增大,于是我们就需要将右边界缩小。若S-Yi=0,这是最理想的情况了,就可以直接退出二分。

      大体确定了,还剩下一个问题对于一个W我们如何快速的求出Y。考虑到矿石的价值与数量(wi>=W)是满足“区间可减性(我自己造的词)”的,具体就是若设sum[i]表示从1~i中所有满足条件的矿石的价值和,那么区间[L,R]中满足条件的矿石和为sum[R]-sum[L-1],对于矿石出现的数量也是满足这个条件的。于是我们可以先O(n)扫一遍求出价值与数量的前缀和,然后在O(m)扫一遍所有区间将每个区间的Y值加起来就可以了。总的时间复杂度为O((m+n)log(maxwi))。

    附上代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=200005;
    
    int n,m,l=1,r;
    ll S,ans=((ll)1<<61);
    ll sum[N],Fre[N];
    
    struct point1{
        int w,v;
    }mine[N];
    
    struct point2{
        int L,R;
    }Sec[N];
    
    int read(){
        int x=0;
        char ch=getchar();
        while(ch<'0' || ch>'9') ch=getchar();
        while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return x;
    }
    
    int main(){
        scanf("%d%d%lld",&n,&m,&S);
        for(int i=1;i<=n;++i){
            mine[i].w=read(),mine[i].v=read();
            r=max(mine[i].w,r);
        }
        for(int i=1;i<=m;++i) Sec[i].L=read(),Sec[i].R=read();
        while(l<=r){
            memset(sum,0,sizeof(sum)),memset(Fre,0,sizeof(Fre));
            ll ret=0;
            int W=(l+r)>>1;
            for(int i=1;i<=n;++i){//求前缀和
                if(mine[i].w>=W) sum[i]=sum[i-1]+mine[i].v,Fre[i]=Fre[i-1]+1;
                else sum[i]=sum[i-1],Fre[i]=Fre[i-1];    
            }
            for(int i=1;i<=m;++i)
                ret+=(sum[Sec[i].R]-sum[Sec[i].L-1])*(Fre[Sec[i].R]-Fre[Sec[i].L-1]);//求Y值
            ll t=S-ret;
            if(t>0){
                ans=min(ans,t);
                r=W-1;
            }else if(t<0){
                ans=min(ans,-t);
                l=W+1;
            }else if(t==0){
                ans=0;
                break;
            }
        }
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    windows文件名非法字符过滤检测-正则表达式
    IEflash遇到flash遮挡
    打印iphone支持的所有字体
    xml字符串转xml对象,xml对象转json对象
    本地windows安装memcached服务
    resin启动时报错com.caucho.config.LineConfigException的解决
    8个Javascript小技巧,让你写的代码有腔调
    如何在MySQl数据库中给已有的数据表添加自增ID?
    mysql删除重复数据方法
    用Rem来无脑还原Web移动端自适应的页面
  • 原文地址:https://www.cnblogs.com/Asika3912333/p/11741189.html
Copyright © 2011-2022 走看看