[NOIP2018] car ferry - Optimization of the slope dp

There \ (n-\) individual, respectively (t_i \) \ time reaches the originating station. Car ferry from the originating station to the terminal to the originating station requires \ (m \) minutes. Every time you start a free shuttle bus schedule. Find the minimum sum-up time and the like. \ (n \ leq 500, m \ leq 500, t_i \ leq 4 \ times 10 ^ 6 \)

Solution

Set \ (f [i] \) represents the last shuttle bus departure time is \ (i \) , all \ (t \ leq i \) in humans, a total of how much time waiting for the bus

Set \ (s [i] \) represents all \ (t \ leq i \) a person \ (T \) and, \ (C [I] \) represents \ (t \ leq i \) human number, then
\ [f [i] = \
max_ {j \ leq im} f [j] + (c [i] -c [j]) i- (s [i] -s [j]) \] optimization considering the slope, into the standard form
\ [f [j] + s
[j] = ic [j] + (s [i] -ic [i]) + f [i] \] Accordingly disposed \ (y [j ] = F [J] + S [J], \ X [J] = C [J] \) , provided \ (A [i] = i , B [i] = s [i] -ic [i] \ ) , then
\ [y = Ax + B +
f [i] \] wherein \ (f [i] \) to be minimized, so to maintain the convex hull

Note, however, due to restrictions on the location of the transition point \ (J \ Leq IM \) , so we need to maintain a length of \ (m \) queues, each processed \ (I \) after, if the size of the queue \ (= m \) , taken from the head-of-state point \ ((x, y) \ ) is inserted into the convex hull, and the state point \ ((x [i], y [i]) \) inserting the tail

#include <bits/stdc++.h>
using namespace std;

const int N = 4000005;
const int M = 5005;
int n,m,t[M],s[N],c[N],f[N],x[N],y[N],q[N],head,tail,h;

double slope(int b,int a) {
    if(x[a]==x[b]) return 1.0*(y[a]-y[b])/(1e-9);
    return (double)(y[a]-y[b])/(x[a]-x[b]);
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>t[i];
    for(int i=1;i<=n;i++) c[t[i]]++, s[t[i]]+=t[i];
    for(int i=1;i<=n;i++) h=max(h,t[i]);
    for(int i=1;i<h+m;i++) c[i]+=c[i-1], s[i]+=s[i-1];
    head=1; tail=0;
    for(int i=0;i<h+m;i++) {
        if(i-m>=0) {
            while(head<tail && slope(q[tail-1],q[tail])>=slope(q[tail],i-m)) --tail;
            q[++tail]=i-m;
        }
        while(head<tail && slope(q[head],q[head+1])<=i) ++head;
        int j=q[head];
        f[i]=c[i]*i-s[i];
        if(head<=tail) f[i]=min(f[i],f[j]+(c[i]-c[j])*i-s[i]+s[j]);
        x[i]=c[i];
        y[i]=f[i]+s[i];
    }
    cout<<*min_element(f+h,f+h+m);
}

Guess you like

Origin www.cnblogs.com/mollnn/p/12457879.html