zoukankan      html  css  js  c++  java
  • P1314 聪明的质检员NOIP 2011T2

    https://www.luogu.org/problem/show?pid=1314#sub
    看到这个题,想到二分是不难的,但是如果就直接上二分,简单暴力地求和,就会超时。O(mnlogw)
    观察题目,区间可能是重合的或者叠盖,就考虑到前缀和来优化,将m*n缩减到m+n。
    最终复杂度为O((m+n)*logw).

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<cmath>
    #define LL long long
    using namespace std;
    int n,m;
    LL s;
    int w[200005],v[200005];
    int L[200005],R[200005];
    LL h[200005],num[200005];
    int l=10000000,r;
    LL check(int x)
    {
        LL y=0,t=0,yy=0;
        /*for(int i=1;i<=m;i++)//O(m*n*logw) TLE 
        {
            y=0,t=0;
            for(int j=L[i];j<=R[i];j++)
             if(w[j]>=x) y+=v[j],t++;
            yy+=t*y;
        }*/
        //memset(h,0,sizeof(h));
        //memset(num,0,sizeof(num));
        for(int i=1;i<=n;i++)//O((m+n)*log w) 
        {
            h[i]=h[i-1];num[i]=num[i-1];
            if(w[i]>=x) h[i]+=v[i],num[i]++;
        }    
        for(int i=1;i<=m;i++)
          yy+=(h[R[i]]-h[L[i]-1])*(num[R[i]]-num[L[i]-1]);
        return yy; 
    }
    int main()
    {
    
        //freopen("qc.in","r",stdin);
        //freopen("qc.out","w",stdout); 
        scanf("%d%d%lld",&n,&m,&s);
        for(int i=1;i<=n;i++)
         scanf("%d%d",&w[i],&v[i]),r=max(r,w[i]),l=min(l,w[i]); 
        for(int i=1;i<=m;i++)
         scanf("%d%d",&L[i],&R[i]);
        int mid;
        LL ans=200000000000;
        while(l<=r)
        {
           mid=(l+r)>>1;
           LL Y=check(mid);
           if(Y<s)
            r=mid-1;
           if(Y>s) 
            l=mid+1;
           if(Y==s) {printf("0
    ");return 0;}
           ans=min(ans,abs(s-Y));
        }
        printf("%lld
    ",ans);
        fclose(stdin);fclose(stdout);
        return 0;
    }
    /*
    5 3 11
    1 5
    2 5
    3 5
    4 5
    5 5
    1 5
    2 4
    3 3
    
    6 
    */ 
    /*
    5 1 5
    1 5
    2 5
    3 5
    4 5
    5 5
    1 3
    
    0*/
    /*
    5 2 11
    1 3
    2 3
    3 3
    4 3
    5 2
    1 5
    2 3
    
    1*/
    
  • 相关阅读:
    VC++ 进度条的使用
    VC++ 知识点
    VC++ 遍历目录
    VC++ 目录选择对话框
    VC中的树形控件
    C++文件输入输出流
    一些有用的Sql语句
    C语言 单引号和双引号的区别
    如何让自己成为一名黑客高手全集
    顶尖黑客的故事
  • 原文地址:https://www.cnblogs.com/dfsac/p/7587907.html
Copyright © 2011-2022 走看看