[NOI2019]ルートホームrouteDAY1T1スロープの最適化[DP]

[ポータル](https://loj.ac/problem/3156)
=
-----
SOL
=
問題の意味:長さnのmは車両の経路上に存在するが、各車両が有する開始$ I $ $ X_ { I} $、端の$ Y_ {I} $、搭乗時間の$ P_ {I} $、時間の$ Q_ {I} $オフ。ポイントの最小数に到達するために$ N $の転送コストで、$ 1 $ -ポイント車から尋ねました。
![ここに画像を挿入説明](https://img-blog.csdnimg.cn/20190716165620585.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMDQwNjU1,size_16,color_FFFFFF,t_70)
注:のみあなたはその場で車を降りることができます。
----

**、考慮DP **
$ X_ {I} <Y_ {満たされてはいないが 、私} $、 時間が限定されるものではなく、および$ P_ {I} <Q_ { I} $を、 そう何の後遺症がありません。
状態が$ O(M)$の合計量を見つけることは困難であり、DPが$ [i]は$ $ I $ $ Y_ {I} $の最小コストに到達する最初のカーシートは、$ Q_ {I} $時間を示す
(全時間$ Q_ {S_ {K}} $ 最後に追加回答)
$$ DP [I] =分(DP [J] + *(-q_ P_ {I} {J})*(P_ {{I} -q_ J})+ B×(P_ {I} -q_ {J})+ C)$$
満足の$ X_ {I} = Y_ { J} $、$ P_ {I}> = Q_ {J} $。

式は変形
$$ 2 * A * P_ {I } * Q_ {J} + DP [i]が- (*のP_は、{i}は* P_ {I} + B *のP_ {I} + C)は、DP [J] = + A * Q_ {J} * Q_ {J} -B * Q_ {J} $$
$(x、y)は$の決定点へ、そこ$ X = Q_ {J} $ 、$ yを= DP [J] + A * Q_ {J} * Q_ {J} -B * Q_ {J} $。
---
**第二に、コレクションを維持するために決定を検討してください。**
時間$ tの$の集合の凸包を維持し、各車両$ U、Vの$、の始点と終点のために。決定ポイントの$ Q_ {I} <= Tを満たすように設定 $を。
方法:$ O(M *ログM )$
 $ $ SETとは、現在の議論の$ X_で、{I} $を$ Uは、Vの$ポイントを追加するように取り付けられ、プレスの$ Q_ {I} $昇順追加しました。
 
方法2:$ O(M)$の
バケットソート排出
$ J $の$ Q_ {J} $時に決定ポイントを、$ Y [J]凸包の$を加えました。現在のポイントの時間の$の$ X_ {I}でiは$、$ P_ {I}質問$は凸包を$。
-----
CODE
=
$のO(M)$
`CPP
// O(M)
の#include <ビット/ STDC ++ H>
使用して名前空間std。
#define SFのscanf
の#define PFのprintf
の#define LL長い長い
赤色()内の#define
の#defineのCS CONST
の#defineのGC GETCHAR()
の#define DB二重
の#define RINTレジスタINT
の#define SE第二
の#define Fiの最初の
インラインint型の赤( ){
 int型NUM = 0、F = 1;チャーC = GC。
 用(;!isdigit(C); C = GC)の場合(C == ' - ')は、f = -1;
 用(; isdigit(C); C = GC)NUM =(NUM << 1)+(NUM << 3)+(C ^ 48)。
 num個の* Fを返します。
}
CS INT N = 2E5 + 10。
構造体PI {
 LLのX、Y。
 int型のID。
}。
int型P [N]、Q [N]、X [N]、Y [N]、N、M、A、B、C、ヘッド[N]。
キュー<整数>のres [3100];
ベクター<PI> QUE [N]。
ベクター<整数> D [3200]。
LL DP [N]、ANS = 1E18。
インラインDB勾配(CSのPIと、CSのPI&B){
 1.0を返す*(AY-によって)/(1.0 *(AX-BX))。
}
インラインボイドgetin(CSはint&I){
 int型のPOS = Y [i]は、
 PI今=(PI){Q [i]は、DP [I] + *のQ [I] * Q [I] -B * Q [i]は、I}。
 一方、(QUE [POS] .size() -頭[POS]> = 2){
  int型LEN = QUE [POS] .size()。
  IF(傾き(QUE [POS] [lenの-1]、QUE [POS] [lenの-2])<スロープ(QUE [POS] [lenの-2]を、今))破ります。
  QUE [POS] .pop_back()。
 }
 QUE [POS] .push_back(今)。
}
インラインボイドgetout(CS DB&SLP、CSのINT&POS){
 一方、(QUE [POS] .size() -頭[POS]> = 2){
  IF(傾き(QUE [POS] [ヘッド[POS]、QUE [POS] [ヘッド[POS] +1])> SLP )を返します。
  ++ヘッド[POS]。
 }
}
{main()の署名された
 N = M =中、A =中、B =において、C =中に、
 {(; I <= M ++ iはRINT I = 1)のために
  X [I] =において、Y [i]は=において、P [I] = [I] =においてQ、で;
 }
 D [P [I]一back(I)(; I <= M + I RINT I = 1)のために、
 QUE [1] .push_back((PI){0,0,0})。 
 私はint型。
 用(RINTのT = 0、T <= 3000; ++ T){
  (!RES [T] .empty())、一方getin(RES [T] .front())、RES [T] .pop()。
  INT LEN = D [T] .size()。
  用(RINTのTMP = 0; TMP <LEN; ++ TMP){
   int型I = D [T] [TMP]。
   int型のPOS = xの[I]。
   IF(QUE [POS] .size()<=ヘッド[POS])続けます。
   = 2.0 dBのSLP *のP [I]。
   (SLP、POS)getout。
   INT J = QUE [POS] [ヘッド[POS] ID。
   DP [i]はDP [J] + 1LL * A *(P [I] -q [J])*(P [I] -q [J])+ 1LL * B *(P [I] -qを[= J])+ C。
   RES [Q [I]プッシュ(I)。
   もし(Y [I] == N){
    ANS =分(ANS、DP [I] + Q [I])。
   }
  }
 }
 COUT << ANS。
 0を返します。
}
`
-----
の$ O(Mの*の関数logm)$
` CPP
// O(M *関数logm)
の#include <ビット/ STDC ++ H>
名前空間STDを使用して、
#define SFのscanf
の#define PFのprintf
の#define LL長い長い
赤色()内の#define
の#defineのCS CONST
の#defineのGC GETCHAR()
の#define DB二重
の#define RINTレジスタINT
の#define SE第二
の#define Fiの最初の
インラインint型の赤( ){
 int型NUM = 0、F = 1;チャーC = GC。
 用(;!isdigit(C); C = GC)の場合(C == ' - ')は、f = -1;
 用(; isdigit(C); C = GC)NUM =(NUM << 1)+(NUM << 3)+(C ^ 48)。
 num個の* Fを返します。
}
CS INT N = 2E5 + 10。
構造体PI {
 LLのX、Y。
 int型のID。
}。
typedefのペア<int型、int型> PA;
INT ORD [N]、P [N]、Q [N]、X [N]、Y [N]、N、M、A、B、C。
セット<PA> RES [N]。
両端キュー<PI> QUE [N]。
LL DP [N]、ANS = 1E18。
BOOL CMP(INT A、INT B){戻りP [A] <P [B];}
インラインDB勾配(CSのPIと、CSのPI&B){
 / 1.0 *(AY-による)を返す(1.0 *(AX- BX));
}
インラインボイドgetin(CS INT&I、CS INT&POS){
 // COUT << "getinする\ n" << I << ' '<< POS <<'の\ n';
 一方、(!RES [POS] .empty()){
  PAさt = * RES [POS] .begin()。
  もし(t.fi> P [i])とブレーク。
  PI今=(PI){t.fi、DP [t.se] *のt.fiを+ * t.fi-Bの*のt.fi、t.se}。
  一方、(QUE [POS] .size()> = 2){
   パイA = QUE [POS] .back(); QUE [POS] .pop_back()。

   IF(傾き(B、A)<スロープ(B、今)){
    QUE [POS] .push_back(A)。
    ブレーク; 
   }
  }
  // COUT << now.x << ' '<< now.y <<' '<< now.id <<'の\ n';
  QUE [POS] .push_back(今)。
  RES [POS] .erase(T)。
 }
// COUT << "SIZ:" << QUE [POS] .size()<< 'の\ n';
}
インラインボイドgetout(CSのDB&SLP、CS INT&POS){
// COUT << "SLP:" << SLP << 'の\ n';
 一方、(QUE [POS] .size()> = 2){
  パイA = QUE [POS] .front(); QUE [POS] .pop_front()。
  PI B = QUE [POS] .front()。
 // COUT << "スロープ" <<スロープ(B、A)<< 'の\ n';
  IF(傾き(B、A)>
   SLP){ QUE [POS] .push_front(A)。
   返します。 
  }
 }
}
{main()の符号付き
// freopenは( "data.in"、 "R"、STDIN)。
 N = M =中、で、A =中、B =において、C =で;
 // SF( "%D%D%D%D%D"、&N、&M&A、&B、&C)。
 {(; I <= M ++ iはRINT I = 1)のために
  X [I] =において、Y [i]は=において、P [I] = [I] =においてQ、で;
  // SF( "%D%D%D%D"、およびX [i]は、&​​Y [i]は、&​​P [i]は、&​​Q [I])。
  ORD [I] = I。
 }
// random_shuffle(ORD + 1、ORD + M + 1)。
 ソート(ORD + 1、ORD + M + 1、CMP)。
 QUE [1] .push_back((PI){0,0,0})。
 (; <= M O; RINT 0 = 1 ++ O)用{
  INT I = ORD [O]。
  int型のPOS = xの[I]。
 // coutの<< "ターン: "<< O <<" \ nを";
  getin(I、POS);
  IF(QUE [POS] .empty())続けます。
  = 2.0 dBのSLP *のP [I]。
  (SLP、POS)getout。

  DP [i]はDP [J] + 1LL * A *(P [I] -q [J])*(P [I] -q [J])+ 1LL * B *(P [I] -qを[= J])+ C。
 // COUT << Q [I] << ' '<< Y [I] <<' '<< DP [Q [I] [Y [I]] <<'の\ n';
  RES [Yの[I]挿入(make_pair(Q [i]は、I))。
  もし(RES [Y [I]サイズ()> 50000)getin(I、Y [I])。
  もし(Y [I] == N){
   ANS =分(ANS、DP [I] + Q [I])。
  }
 }
 COUT << ANS。
 0を返します。
}
`` `
 

おすすめ

転載: www.cnblogs.com/rhjoi/p/11355328.html