タイトルの説明
毎年1024プログラマフェスティバルで、Dark Horse Programmersが大きな祝賀会を開きます。今年のプログラマーデーも例外ではなく、すべてのクラスメートがオレンジを送ります。
クラスでは、前から後ろに n 人の学生が一列に並んでいて、これらの学生の結果を学習しました。i番目の学生のスコアはai です。校長は、前の段階での生徒のテストのスコアに基づいてオレンジの数を評価したいと考えています。優秀な学生をやる気にさせるには、オレンジを送る際に次の要件を満たす必要があります。
- 隣接するクラスの成績が良い生徒のオレンジはもっと多いはずです。隣接するクラスメートが同じ成績を持っている場合、彼らは同じ金額を受け取る必要があります。
- 各生徒には少なくとも1つのオレンジが割り当てられます
予算が限られているため、校長は要件に応じてできるだけ少ないオレンジを出すことを望んでいます。すみません、オレンジはいくつ準備する必要がありますか。
入力フォーマット
最初の行は正の整数n で、学生の数を示す 10 ^ 6以下です。
次の行には、10 ^ 9を超えない n個 の非負の整数aiがあり、i 番目のクラスメートのスコアを示しています。
出力フォーマット
答え、つまり、準備する必要があるオレンジの数を出力します。
入力例:
11
3 6 9 4 7 7 2 13 15 15 19
出力例:
24
アイデア:これは順方向および逆方向の非減少サブ列です。すべての人がオレンジ色になるように初期化してから、配列をトラバースします。後者は前のスコアよりも高く、次にオレンジがもう1つあり、配列全体を繰り返します。減算せずにサブ列を見つけ、最後に合計する配列を合計します。
#include <cstdio> #include < string .h> #include <iostream> #include <algorithm> #include <sstream> #include <math.h> #include <map> using namespace std; const int inf = 999999 ; // 0x7fffff const long long mod = 1e9 + 7 ; const double PI = acos(-1 ); long long n、m; long long ans = 0 ; ブールvis [ 105 ]; long long dis [ 10000000 ]、get [ 10000000 ]; int main() { cin >> n; for(int i = 1 ; i <= n; i ++ ){ cin >> dis [i]; get [i] = 1 ; // get配列を初期化し ます。これ は、各学生が少なくとも1つのオレンジ } を持っているためです(int i = 2 ; i <= n; i ++){ // 配列を左から右にスキャンし ます。 衰えない子列を見つけるために、左から右に あれば(dis [i]> dis [i- 1 ]){ // 次の生徒のスコアが前の生徒のオレンジの数よりも大きい場合、前の生徒よりもオレンジが1つ多い get [i] = get [i- 1 ] + 1 ; } else if(dis [i] == dis [i- 1 ]){ // スコアはオレンジの数と等しくなければならない get [i] = get [i- 1 ]; } } for(int i = n- 1 ; i > = 1 ; i-){ // 次に、配列を右から左にもう一度スキャンし、右から左に非減少サブ列も見つけます if(dis [i]> dis [i + 1 ]){ get [i] = max(get [i]、get [i + 1 ] + 1); // 同様に、等級の高いオレンジの数は、隣にある等級の低いオレンジの数よりも1つ多いですが、最初のソート結果を考慮する必要があります。最後の結果と前の結果の大きい方 } else if(dis [i] == dis [i + 1 ]){ // 等しいオレンジ の数も等しくなければならないget [i] = get [i + 1 ]; } } for(int i = 1 ; i <= n; i ++){ // オレンジの数を累積 ans + = get [i]; } cout << ans; 0を返します。 }