牛客网暑期ACM多校训练营(第二场)G transform(二分)

题意:有n个位置,每个位置的坐标为x[i],有桶a[i]个。你现在要把若干个桶移动到同一个位置,求在移动总距离不超过T/2的情况下,最多可以将多少个木桶移动到同一个位置?(n<=5e5,T<=1e18,x[i]<=1e9,a[i]<=1e5)

思路:二分。如官方题解所说,我们要使移动的总距离最小,那么最终被移动的桶在数轴上一定是一段连续的区间。如果固定了这个区间,那么最优方案就是把这个区间的所有桶移动到这个区间的某个位置。而这个位置在这个区间内满足先单减再单增,在总体区间满足单调递增。我们固定这段连续区间的起点,那么区间的终点也是总体单增的。因此只需要O(n)枚举区间左端点。

我们用s[i]表示前i个位置有多少个桶,t[i]表示前i个位置的所有桶从0坐标移动过来的距离和。

假设我们二分到可以搬x个桶到同一个位置,当前判断的连续区间为[lp+1,rp],则首先s[rp]-s[lp]>=x。此时会有两种情况,就是我们在这个区间内要挑出x个桶。显然多余的桶一定在a[rp]或者在a[lp](因为我们单调枚举左端点)。当在a[rp]时,我们就不需要搬那多余的(s[rp]-s[lp]-x)个桶了。于是我们枚举这x个桶搬到某个位置x[i]时,区间下标[lp+1,i]的桶搬到x[i]的总距离为:

(s[i]-s[lp])*d[i]-(t[i]-t[lp]);

区间下标[i,rp]的桶搬到x[i]的总距离为(除去多余的桶和上一步已经搬了的桶):

t[rp]-t[lp]-(s[rp]-s[lp]-x)*d[i]-(t[i]-t[lp])-(x-(s[i]-s[lp]))*d[i];

以上式子需要好好思考一下。

当在a[lp]时与以上情况类似。此时需要从右往左枚举区间右端点。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=5e5+10;
int n;
ll T,o,p,lp,rp,a[maxn],d[maxn],t[maxn],s[maxn],mp;
ll c1(int i)
{
    return (s[i]-s[lp])*d[i]-(t[i]-t[lp])+(o-t[i]+t[lp])-(p-s[i]+s[lp])*d[i];
}
ll c2(int i)
{
    return -(s[rp]-s[i])*d[i]+(t[rp]-t[i])-(o-t[rp]+t[i])+(p-s[rp]+s[i])*d[i];
}
bool jud(ll x)
{
    p=x;
    lp=0;rp=1;mp=1;
    while(1)
    {
        while(rp<n&&s[rp]-s[lp]<x) rp++;
        if(s[rp]-s[lp]<x) break;
        o=t[rp]-t[lp]-(s[rp]-s[lp]-x)*d[rp];
        while(mp<n&&c1(mp)>c1(mp+1))mp++;
        if(c1(mp)<=T)return 1;
        lp++;
    }
    lp=n-1;rp=n;mp=n;
    while(1)
    {
        while(lp>0&&s[rp]-s[lp]<x) lp--;
        if(s[rp]-s[lp]<x) break;
        o=t[rp]-t[lp]-(s[rp]-s[lp]-x)*d[lp+1];
        while(mp>1&&c2(mp)>c2(mp+1))mp--;
        if(c2(mp)<=T)return 1;
        rp--;
    }
    return 0;
}
int main()
{
    scanf("%d %lld",&n,&T);T>>=1;
    for(int i=1;i<=n;i++) scanf("%lld",&d[i]);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++) {s[i]=s[i-1]+a[i];t[i]=t[i-1]+a[i]*d[i];}
    ll l=0,r=s[n]+1;
    while(l+1<r)
    {
        ll mid=(l+r)>>1;
        if(jud(mid)) l=mid;
        else r=mid;
    }
    printf("%lld\n",l);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lsd20164388/article/details/81152298
今日推荐