Summer ACM multi school training camp (the second session) G (thinking + simple dichotomy)

Title Link: Portal
The meaning of the question is very simple. I'll give you n points. The coordinates of the points are x[i]. Each point has num[i] items. It costs 2*abs(x[u]-x[v]) to transport an item in U position to v. how many items can be moved to a point at most in T cost

The direct dichotomy answer is to find a way to move the object in o(1)
Open two arrays d[i] to represent the cost of moving the first d[i] items to 0. It's not difficult to find another array d[i]=d[i-1]+num[i]*x[i] to record the prefix sum of items. I've dealt with the num array directly

Moving items in [l r] range to i is
1. [l+1,i] move the number of items in the interval from 0 to i minus [l+1,i] move the items in the interval to 0 (move more to)
2. [i+1,r] similarly

In this way, how to find the intermediate value i? Because the movement increases with i, you must first reduce the single value and then find the lowest value directly
Why is it on both sides? The number of items found each time is not necessarily exactly k, so we need to remove several items, which must be the right or left end of the interval

Code
It doesn't feel like a positive solution. If you compare it directly with i, it will time out.... there is a lot of difference between it and big guy code time

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rd(a) scanf("%d",&a)
#define rlld(a) scanf("%lld",&a)
#define me(a,b) memset(a,b,sizeof(a))
const int maxn=5e5+10;
const ll mod =1e9+7;
ll num[maxn];
ll x[maxn];
ll d[maxn];
ll n;
ll t;
inline ll solve(int f,int i,int l,int r,int nu){
    if(!f){

    return -d[i]+d[l]+(num[i]-num[l])*x[i]+d[r]-d[l]-(num[r]-num[l]-nu)*x[r]-(d[i]-d[l])-(nu-num[i]+num[l])*x[i];
    }

    return d[r]-d[i]-(num[r]-num[i])*x[i+1]-d[r]+d[l]+(num[r]-num[l]-nu)*x[l+1]+(d[r]-d[i])+(nu-num[r]+num[i])*x[i+1];
}
bool judge(ll xx,ll limit){
    ll l=0;
    ll i=1;
    ll r=1;
    ll temp;
    while(1){
        while(r<=n&&num[r]-num[l]<xx) r++;
        if(num[r]-num[l]<xx) break; 
        temp=solve(0,i,l,r,xx);
        while(i<=n) {
            ll o=solve(0,i+1,l,r,xx);
            if(temp>=o)  {
                temp=o;i++;
            }
            else  break;

        }

        if(temp*2<=limit) return true;
        l++;
    }
    l=n-1;
    r=n;
    i=n-1;
    while(1){
        while(l>=0&&num[r]-num[l]<xx) l--;
        if(num[r]-num[l]<xx) break; 
            temp=solve(1,i,l,r,xx);
        while(i>0) {
            ll o=solve(1,i-1,l,r,xx);
            if(temp>=o)  {
                temp=o;i--;
            }
            else  break;

        }

        if(temp*2<=limit) return true;
        r--;        
    }


    return false;
}
int main(){


    rlld(n),rlld(t);
    for(int i=1;i<=n;i++) {
        rlld(x[i]);
    }

    for(int i=1;i<=n;i++) {
        rlld(num[i]);

    }   
    for(int i=1;i<=n;i++) 
    {       
            d[i]=d[i-1]+x[i]*num[i];
            num[i]+=num[i-1];
    }

    ll r=num[n];
    ll l=0;
    ll ans;
    while(l<=r){
        ll mid =(l+r)/2;
        if(judge(mid,t)) {
            l=mid+1;
            ans=mid;
        }
        else r=mid-1; 

    }

    printf("%lld",ans);

}

Posted by seraulu1 on Fri, 31 Jan 2020 02:32:21 -0800