牛客多校第二场 G transform(二分)

链接:https://www.nowcoder.com/acm/contest/140/G
来源:牛客网
 

题目描述

White Cloud placed n containers in sequence on a axes. The i-th container is located at x[i] and there are a[i] number of products in it.
White Rabbit wants to buy some products. The products which are required to be sold must be placed in the same container.
The cost of moving a product from container u to container v is 2*abs(x[u]-x[v]).
White Cloud wants to know the maximum number of products it can sell. The total cost can't exceed T.

输入描述:

The first line of input contains 2 integers n and T(n <= 500000,T <= 1000000000000000000)
In the next line there are n increasing numbers in range [0,1000000000] denoting x[1..n]
In the next line there are n numbers in range[0,10000] denoting a[1..n]

输出描述:

Print an integer denoting the answer.

示例1

输入

复制

2 3
1 2
2 3

输出

复制

4

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

题目思路:既然要使得花费在不超过T的情况尽可能多的移动货物,那么我们肯定是将一个区间内的所有货物移到坐标中位的集装箱上。那么我们就可以对答案进行二分,然后枚举所要移动的区间的左端点,再找到中位点和右端点,然后判断这个区间移动的花费是否小于T。

求区间花费的话我们可以用两个前缀和和两个后缀和来求,

prew[i]表示前 i 个集装箱的总货物,prex[i]表示将前 i 个集装箱的货物移动到第 i 个集装箱的花费,那么可以得到如下两个式子

prew[i]=prew[i-1]+a[i]

prex[i]=prew[i-1]*(x[i]-x[i-1])+prex[i-1]

那么将 l 到 r 这个区间内所有的货物移动到 r 这个集装箱的花费就为

prex[r]-prex[l-1]-prew[l-1]*(x[r]-x[l-1])

sufw[i]表示第 i 个到第 n 个集装箱的总货物,sufx[i]表示将第 i 个到第 n 个集装箱所有的货物移动到第 i 个集装箱的花费,那么可以得到如下两个式子

sufw[i]=sufw[i+1]+a[i]

sufx[i]=sufw[i+1]*(x[i+1]-x[i])+sufx[i+1]

那么将 l 到 r 这个区间内所有的货物移动到 l 这个集装箱的花费就为

sufx[l]-sufx[r+1]-sufw[r+1]*(x[r+1]-x[l])

二分判断的过程中,由于最终的答案不一定是将整个区间内所有的货物都移动到一个集装箱,所以我们还要判断最后剩余的货物是从最左端的集装箱移动到中位点还是从最右端移动到中位点,然后再根据花费的大小情况进行二分就可以得到最终答案了。

代码如下:

#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define FIN freopen("in.txt","r",stdin)
#define fuck(x) cout<<"["<<x<<"]"<<endl
#define IOS ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pii;
const int MX=5e5+7;
 
int n;
ll T,prex[MX],prew[MX],sufx[MX],sufw[MX];
struct node{
    ll x,w;
 
    bool operator<(const node &node1)const{
        return x<node1.x;
    }
}a[MX];
ll cal_pre(int l,int r){
    return prex[r]-prex[l-1]-prew[l-1]*(a[r].x-a[l-1].x);
}
ll cal_suf(int l,int r){
    return sufx[l]-sufx[r+1]-sufw[r+1]*(a[r+1].x-a[l].x);
}
 
bool check(ll num){
    ll num2=num/2+1;
    int l=1,r=2,mid=2;
    while(1){
        while(r<=n && prew[r]-prew[l-1]<num) r++;
        while(mid<=n && prew[mid]-prew[l-1]<num2) mid++;
        if(r>n || mid>n) break;
        ll s=cal_pre(l,mid)+cal_suf(mid,r-1)+(num-(prew[r-1]-prew[l-1]))*(a[r].x-a[mid].x);
        if(s<=T) return true;
        l++;
    }
    l=n-1;r=n;mid=n;
    while(1){
        while(l>=1 && prew[r]-prew[l-1]<num) l--;
        while(mid>=2 && prew[mid]-prew[l-1]<num2) mid--;
        if(l<1 || mid<2) break;
        ll s=cal_pre(l+1,mid)+cal_suf(mid,r)+(num-(prew[r]-prew[l]))*(a[mid].x-a[l].x);
        if(s<=T) return true;
        r--;
    }
    return false;
}
 
int main(){
    IOS;
    cin>>n>>T;T/=2;
    for(int i=1;i<=n;i++) cin>>a[i].x;
    for(int i=1;i<=n;i++) cin>>a[i].w;
    sort(a+1,a+n+1);
    ll l=1,r=0;
    prex[0]=prew[0]=0;
    sufx[n+1]=sufw[n+1]=0;
    for(int i=1;i<=n;i++){
        prew[i]=prew[i-1]+a[i].w;
        prex[i]=prew[i-1]*(a[i].x-a[i-1].x)+prex[i-1];
        r+=a[i].w;
    }
    for(int i=n;i>=1;i--){
        sufw[i]=sufw[i+1]+a[i].w;
        sufx[i]=sufw[i+1]*(a[i+1].x-a[i].x)+sufx[i+1];
    }
    while(l<=r){
        ll mid=(l+r)>>1;
        if(check(mid)) l=mid+1;
        else r=mid-1;
    }
    cout<<r<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lee_w_j__/article/details/81157488