zoukankan      html  css  js  c++  java
  • [Ioi2011] ricehub

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2600

    这道题按说是当年较为水的一道题,但是我没有独立想出。

    相当于是找出一个最长的序列使得所有的数字与中位数差值的绝对值之和(就是运费)最小。

    基本的思路是二分答案,因为如果存在长度为x的一个序列的话,一定也存在长度为x-1的一个序列。

    关键就是O(n)检验二分出的答案。

    可以发现通过分类讨论是可以快速统计所有的长度为L的运费的。

    假设二分出的长度为len。

    初始有一个区间 [1,len] 然后每一次只要从 [l,r] 转移到 [l+1,r+1] 即可。

    很好转移,相当于先删除掉 l 这个位置上的数字与中位数的差值,而后加上 r 这个位置的数与中位数的差值。

    中位数的变化是1或者0,加上(mid-l+1)减去(r-mid)即可。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    #define LL long long
    #define N 400010
    
    using namespace std;
    
    int n;
    LL L,B,x[N];
    
    inline LL Abs(LL x){
        if(x<0) return -x;
        return x;
    }
    
    inline bool check(int len){
        LL ans=0;
        for(int i=1;i<=len;i++)
            ans+=Abs(x[(len+1+1)>>1]-x[i]);
        if(ans<=B) return 1;
        int mid=(len+1+1)>>1;
        for(int l=2;l<=n-len+1;l++){
            int r=l+len-1;
            ans-=x[mid]-x[l-1];
            mid=(l+r+1)>>1;
            ans+=(mid-l)*(x[mid]-x[mid-1]);
            ans-=(r-mid)*(x[mid]-x[mid-1]);
            ans+=x[r]-x[mid];
            if(ans<=B) return 1;
        }
        return 0;
    }
    
    int main(){
        scanf("%d%lld%lld",&n,&L,&B);
        for(int i=1;i<=n;i++) scanf("%lld",&x[i]);
        int l=1,r=n;
        while(r-l>10){
            int mid=(l+r)>>1;
            if(check(mid)) l=mid;
            else r=mid;
        }
        for(;r>=l;r--) if(check(r)) break;
        printf("%d
    ",r);
        return 0;
    }
    Code
  • 相关阅读:
    如何使用jpegtran 压缩JPG图片
    JS获取后台返回的JSON数据
    VUE安装步骤1
    VUE安装步骤
    SVN使用教程总结
    WebStorm的下载与安装
    理解CSS3 transform中的Matrix(矩阵)
    http statusCode(状态码) 200、300、400、500序列详解
    JS如何获取屏幕、浏览器及网页高度宽度?
    html5使用local storage存储的数据在本地是以何种形式保存的
  • 原文地址:https://www.cnblogs.com/lawyer/p/4548443.html
Copyright © 2011-2022 走看看