[Solution] task scheduling problem (slope optimization)

[ SDOI2012] task scheduling

The slope Optimization Starter questions:

Set \ (f (x) \) of \ (F (x) \) of the post- conjugation and, \ (T (X) \) of \ (T (x) \) prefix and. \ (dp (i) \) indicating the completion of the first \ (i \) mandate minimum cost transfer:

\(dp(i)=\min \{dp(j) +f(j+1)\times(S+t(i)-t(j)) \}\)

Remove:

  • And \ (j \) has nothing: no
  • And only \ (j \) Related: \ (dp (J) + f (J + 1) \ Times (St (J)) \)
  • And \ (i, j \) Related: \ (F (J +. 1) \ Times T (I) \)

We only found and (j \) \ can be directly related to the pre-treatment, the question now is to determine the \ (i \) How to quickly find a \ (j \)

Order \ (y_j = DP (J) + F (J +. 1) \ Times (St (J)) \) , \ (x_j = F (J +. 1) \) , the original formula can be written as:
\ [DP (I ) = y_j + x_jt (i) \]

Click conversion equation
\ [y_j = -t (i) x_j + dp (i) \]

The question now becomes identified a \ (i \) , to quickly find a previous \ (j \) so that \ (dp (i) \) Minimum

This thing as a straight line, it becomes I have a translation in the plane of the slope \ (- t (i) \ ) is a straight line, find a point now \ ((x_j, y_j) \ ) makes too at this point the slope is \ (- t (i) \ ) a straight line intercept as small as possible.

Blue: slope \ (- t (i) \ ) line

Purple Point: \ ((x_j, y_j) \)

Obviously, there can be seen in a \ (y \) is negative infinity axle has slowly move in a straight line (intercept gradually become larger), this line passes through the point in a sudden we set it At this intercept is the smallest of the intercept. Obviously, in this convex hull above a certain point, and the slope of the left and right sides of this point it must be left smaller, larger on the right (negative slope).

Dynamic Maintenance look like a convex hull.

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;  typedef long long ll;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(c<48||c>57)f|=c==45,c=getchar();
      while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}
int n,s;
const int maxn=3e5+5;
int Ti[maxn],Fi[maxn];
ll st[maxn],sf[maxn];
ll x[maxn],y[maxn],q[maxn],dp[maxn];
int cnt;

inline ll getval(const int&i,const int&j){
      return dp[j]+sf[j+1]*(s+st[i]-st[j]);
}

inline bool chek0(const int&i,const int&j,const ll&k){
      return (long double)1.0*((y[i]+dp[i])-(y[j]+dp[j]))*(x[i]-x[k])<=(long double)1.0*((y[i]+dp[i])-(y[k]+dp[k]))*(x[i]-x[j]);
}

inline bool chek(const int&i,const int&j,const ll&k){
      return (long double)1.0*(y[i]+dp[i])-(y[j]+dp[j])<=(long double)1.0*k*(x[i]-x[j]);
}

inline int lookup(const ll&k){
      register int l=1,r=cnt-1,ret=cnt,mid;
      while(l<=r){
        mid=(l+r)>>1;
        if(chek(q[mid],q[mid+1],k))
          r=mid-1,ret=mid;
        else l=mid+1;
      }
      return q[ret];
}
int main(){
      
      n=qr();s=qr();
      for(register int t=1;t<=n;++t)
        Ti[t]=qr(),Fi[t]=qr(),st[t]=st[t-1]+Ti[t];
      for(register int t=n;t>=0;--t) sf[t]=sf[t+1]+Fi[t];
      for(register int t=0;t<=n;++t) y[t]=sf[t+1]*(s-st[t]),x[t]=sf[t+1];
      q[cnt=1]=0;
      for(register int t=1;t<=n;++t){
        dp[t]=getval(t,lookup(-st[t]));
        while(cnt>1&&chek0(q[cnt-1],q[cnt],t)) --cnt;
        q[++cnt]=t;
      }
      cout<<dp[n]<<endl;
      return 0;
}

Guess you like

Origin www.cnblogs.com/winlere/p/10994580.html