P2672 [NOIP2015普及グループ]営業マン

貪欲なシミュレーション

ポータル

この例から始めましょう

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 * 22(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 _いや_ _nF [ 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;
}

おすすめ

転載: blog.csdn.net/onlyfirer/article/details/126578091
おすすめ