貪欲なシミュレーション
この例から始めましょう
6
1 2 3 4 5 6
4 2 3 5 3 1
現在のX = 1 X = 1の場合バツ=1 、その後FF を構築できますF配列
F [ i ] F[i]F [ i ] は入り口から出入りすることを意味し、最初のa [ i ] a[i]a [ i ]ホームユーザーは販売を促進し、余分な道路を通らず、回答に貢献します
。sは現在の回答を意味します。nownow
を使用してください今、w は最も遠い点を表します
すると、X = 1 X = 1バツ=1回:F [ i ] = s [ i ] ∗ 2 + a [ i ] F[i] = s[i]*2+a[i]F [ i ]=s [ i ]∗2+a [ i ]
F = F =F= { 6 , 6 , 9 , 13 , 13 , 13 6, 6, 9, 13, 13, 13
6 、6 、9 、13 、13 、13 }F[i] F[i]
から始めます。F [ i ]で最大値を選択するだけです。
Setnow = max.id now = max.idさあ_ _=マックス。_ 私は今= 4 今 = 4さあ_ _=4 (実際には 5 または 6 も許容されます
)an s +=F [ 4 ] F[4]F [ 4 ]
(アンアンan s ==13 1313 )F[i]F[i]
にどのような影響があるかを考えてみましょう。F [ i ]の効果は何ですか?X = 2 X = 2
を考慮するとバツ=2時。
若 s [ i ] s[i] s [ i ] <s [ 今 ] s [ 今 ]s [ now ]はs [now ] s[now]にありますsの左側[現在] _
F [ i ] F [ i ]F [ i ] =a [ i ] a[i]ア[イ]
ケイは今行くから現時点での出張販売補足
:実際に最初に販売に行くii私は今指をさして今売りに行きます現在の点の疲労値が同じ場合
、FFFは { 4 , 2 , 3 , / , 13 , 13 4, 2, 3, /, 13, 13 に
4 、2 、3 、/ 、13 、13 }
若 s [ i ] s[i] s [ i ] >s [ 今 ] s [ 今 ]s [ now ]はs [now ] s[now]にありますs [ now ]の右側_
F [ i ] = ( s [ i ] − s [now ] ) ∗ 2 + a [ i ] F[i] = (s[i]-s[now])*2+a[i]F [ i ]=( s [ i ]−[今] ) _ _∗2+ア[イ]
元の距離 ( s [ i ] − s [ now ] s[i]-s[now] )からさらに 2 距離進むことができるためです。s [ i ]−s [現在] ) * 2 * 2※ 2(1往復、1往復)
なのでFFFは { 4 , 2 , 3 , / , 5 , 5 4, 2, 3, /, 5, 5 に
4 、2 、3 、/ 、5 、5 }
さて、 FFからやり直しますF配列の最大値の ID を見つけます
letnow = 6 now = 6さあ_ _=6 (5 55も機能します)
an s += F[6]
(ans ansan s ==18 1818 )
この時は
FFF = { 4 , 2 , 3 , / , 3 , / 4, 2, 3, /, 3, /
4 、2 、3 、/ 、3 、/ }
F [ 5 ] F[5]F [ 5 ] は3 3になります3 、 6 6にあるため6左右に
点がないFFF値
X = 3 X = 3バツ=3時
アンアンan s += F[1]
(ans ansan s ==22 2222 )
FFF = { / 、 2 、 3 、 / 、 3 、 / /、 2、 3、 /、 3、 /
/ 、2 、3 、/ 、3 、/ }
X = 4 X = 4バツ=4時
ですan s += F[3]
(ans ansan s ==25 2525 )
FFF = { / , 2 , / , / , 3 , / /, 2, /, /, 3, /
/ 、2 、/ 、/ 、3 、/ }
X = 5 X = 5バツ=5時
アンアンan s += F[5]
(ans ansan s ==28 2828 )
FFF = { / , 2 , / , / , / , / /, 2, /, /, /, /
/ 、2 、/ 、/ 、/ 、/ }
X = 6 X = 6バツ=6時
アンアンan s += F[2]
(ans ansan s ==30 3030 )
FFF = { / 、 / 、 / 、 / 、 / 、 / /、 /、 /、 /、 /、 /
/ 、/ 、/ 、/ 、/ 、最終的な答えは次の
とおりです。
13
18
22
25
28
30
そこで問題は、最大値を素早く見つけるにはどうすればよいでしょうか? maxn [now] maxn[now]
を使用します。max n [ no w ]表示nownow _いや~ん_ _n中F [ i ] F[i]F [ i ]の最大値 (now < i < = n now < i <= nさあ_ _<私<=n )
maxn [ i ] maxn[i]max x n [ i ]の役割は、今を維持することです。F [ i ]F[i]今の右側F [ i ]の最大値、
今、今現在の左側の最大のa [ i ] a[i][ i ]を維持するにはどうすればよいですか今だ
からnowの左側の値は最大値を削除する操作が必要なので
、maxn maxnは使用できません前処理操作はmax x n
ですが、priority_queue は優れたデータ構造なので、
priority queueqq をq は左側の最大値a [ i ] a[i]a [ i ]の値
これらの操作ではFF が使用されないことがわかります。F配列なので、この配列を作成する必要はなく、
ましてやa [ i ] a[i] は今の左側にあります[ i ] は変化せず、maxn [ now ] maxn[now]max x n [ n o w ] はs [now ] ∗ 2 s[now]*2 を減算するだけで済みます。[今] _ _ _∗2すぐにでもいい
maxn [今] maxn[今]max n [ n o w ] =s [ i ] ∗ 2 + a [ i ] s[i]*2+a[i ]s [ i ]∗2+a [ i ] , ( i$ はこのときの最大値)
somaxn [ now ] − s [ now ] ∗ 2 maxn[now]-s[now]*2最大n [現在] _ _ _−[今] _ _ _∗2 =a [ i ] + s [ i ] ∗ 2 − s [現在] ∗ 2 a[i]+s[i]*2-s[現在]*2ア[イ]+s [ i ]∗2−[今] _ _ _∗2 =a [ i ] + ( s [ i ] − s [now] ) ∗ 2 a[i]+(s[i]-s[now])*2ア[イ]+( s [ i ]−[今] ) _ _∗2は上記のF [ i ] F[i]F [ i ]の値
ACコード:
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10,INF=1e9,mod=INF+7;
int n,now,cnt;
long long ans;
int a[N],s[N];
pair<int,int> maxn[N];
priority_queue<int> q;
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;i++)
scanf("%d",s+i);
for(int i = 1;i <= n;i++)
scanf("%d",a+i);
maxn[n+1].second = -INF;
for(int i = n;i >= 1;i--){
maxn[i] = maxn[i+1];
if(s[i]*2+a[i] >= maxn[i].second)
maxn[i] = make_pair(i,s[i]*2+a[i]);
}
for(int i = 1;i <= n;i++){
int l = (q.empty() ? -INF : q.top());
int r = (now == n ? -INF : maxn[now+1].second);
if(l >= r-s[now]*2){
ans += l;
q.pop();
printf("%lld\n",ans);
}else {
ans += r-s[now]*2;
for(int i = now+1;i <= maxn[now+1].first-1;i++)
q.push(a[i]);
now = maxn[now+1].first;
printf("%lld\n",ans);
}
}
return 0;
}