牛客网多校2 transform(二分+尺取)

题目:在一个数轴上有n个集装箱,第 i 个集装箱的位置为x[i],且在集装箱内装有w[i]件货物,现在将这些集装箱内的货物进行移动(将一件货物从第 i 个集装箱移动到第 j 个集装箱的花费就为2*abs(x[i]-x[j]) ),求在总花费不超过T的情况下,最多能将多少货物移动到同一个集装箱内。

思路:二分一下num个集装箱被移到一起,用尺取判断是否存在可行方案。判断时由num可以确定区间的长度,先按左端点这别的货物都移过去最优时判断,再按右端点优先。因为符合贪心性质,所以肯定会有一个最优的。当选定一个区间时,最终货物集合的地点肯定是中位数(num/2+1)这个位置,注意不是中间位置。

#include
using namespace std;
typedef long long ll;
const int maxn=5e5+10;
struct node{
    ll x,w;
}a[maxn];
bool cmp(const node &a,const node &b)
{
    return a.xn||mid>n) break;
        ll sum=getsum1(l,mid);
        sum+=getsum2(mid,r-1);
        sum+=2*(num-(prew[r-1]-prew[l-1]))*(a[r].x-a[mid].x);
        if(sum<=m) return true;
        l++;
    }
    l=n,r=n,mid=n;
    while(l>0)
    {
        while(l>0&&sufw[l]-sufw[r+1]0&&sufw[mid]-sufw[r+1]=1;i--)
    {
        sufw[i]=sufw[i+1]+a[i].w;
        sufs[i]=sufs[i+1]+2ll*sufw[i+1]*(a[i+1].x-a[i].x);
    }
    ll l=1,r=S,ans=0;
    while(l<=r)
    {
        ll mid=(l+r)>>1;
        if(check(mid))
        {
            ans=mid;
            l=mid+1;
        }
        else
            r=mid-1;
    }
    printf("%lld\n",ans);
    return 0;
}

 

你可能感兴趣的:(二分,多校)