zoukankan      html  css  js  c++  java
  • [bzoj2600][Ioi2011]ricehub_二分

    ricehub bzoj-2600 Ioi-2011

    题目大意:在数轴上有r块稻田,稻田坐标为整数。计划建造一个米仓,使得它可以收取尽量多的稻米。米仓的坐标仍需为整数。每一块权值为val的稻田距离米仓的距离为dis,那么收取这个稻田上的大米的代价是val*dis。我们只有b元运费,问最多能收取多少稻米。

    注释:$1le r le 10^5$,$1le lle 10^9$,$0le ble 2cdot 10^{15}$。

    想法:这就相当于在一个带权的数轴上选取一个点,使得所有点到该点的加权*距离最小。我们不妨将权值为val的点看成是val个不同的点。那么这就相当于在数轴上$sumlimits_{i=1}^{r}val_i$个点,所有点到被选取点的距离(由于已经将点拆过了,所以不加权)最小。显然,是在所有点的中位数(每一个点开成val个)的位置距离和最小。这样的话我们二分,对于每一个二分过程中的中间点check一下即可。

    最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    int n,m,a[100005];
    ll tot,sum[100005];
    bool check(int x)
    {
        int j,mid,pos;
        for(int i=1;i+x-1<=n;i++)
        {
            j=i+x-1;
            mid=i+(x>>1)-1;
            pos=j-(x>>1)+1;
            if(sum[j]-sum[pos-1]-sum[mid]+sum[i-1]<=tot)
                return true;
        }
        return false;
    }
    int main()
    {
        scanf("%d%d%lld",&n,&m,&tot);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        int l=0,r=n;
        while(l+1<r)
        {
            int mid=(l+r)>>1;
            if(check(mid))
                l=mid;
            else r=mid-1;
        }
        if(check(r)) printf("%d
    ",r);
        else printf("%d
    ",l);
        return 0;
    }
    
    

    小结:对于加权的问题,我们可以将它拆掉,看成不加权的问题。

  • 相关阅读:
    ABAPNote001
    ABAPNote002
    共享WinCE6.0 下的一个软件升级程序
    EF参数化查询
    VS2010 调用RFC 时注意(.net4.0) 使用nco
    RDLC报表问题
    参数化查询与拼接SQL代码执行测试
    ABAPNOTE 获取释放的定单
    Wince6.0 + xpsp3+VS2005的一些问题
    BackgroundWorker使用备忘
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9103538.html
Copyright © 2011-2022 走看看