アイデア
質問を注意深く調べると、隣接する値の比較は、正と負の非降順サブシーケンスに少し似ていることがわかります。
突然、最初にすべての非降順のサブシーケンスを見つけることができることがわかりました。次に、このスコアの低い順から高い順に、各人がオレンジをもう1つ分配し(同じスコア、スコアはオレンジと同じ)、最後にオレンジの数を追加します、2つの反対の非下降サブシーケンスのピークは最大値を取ります。
わからない場合は以下のサンプル説明をご覧ください
グレードによると、3、4、5の順方向と逆方向の2つの非下降サブシーケンスがあり、スコアの低い方から高い方まで3ポイントを獲得した人から始まり、山のような外観を形成していることがわかります個人から送信されたオレンジに1を加えます(図の四角はオレンジの数を示します)、答えは図の四角の総数ではないことがわかりますか?
これは、一連の自作のサンプルと説明図であり、前のテキストとコードに従って理解できます。
11
3 6 9 4 7 7 2 13 15 15 19
输出:24 ( 1 2 3 1 2 2 1 2 3 3 4 )
まとめ
- 読み込んで、全員が最初に受け取るオレンジの数(つまり、正方形の数)を1に初期化します。
- 降順でないすべてのサブシーケンスを見つけて、オレンジの数を+1します。
- 同上。(ここで最大値が検出されます)
- 統計、出力。
ACコード
#include<iostream>
#include<cmath>
using namespace std;
int a[1000001],t[1000001],n,k;//a数组存分数,t数组是橘子数即方块数
long long ans;//数值很大
int main()
{
freopen("cpp.in", "r", stdin);
freopen("cpp.out", "w", stdout);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i],t[i]=1;//读入,初始化
for(int i=2;i<=n;i++)//求正着的不降子序列
{
if(a[i-1]<a[i])t[i]=t[i-1]+1;//给橘子数赋值
if(a[i-1]==a[i])t[i]=t[i-1];//分数相同则与上个人相等
}
for(int i=n;i>=2;i--)//求反着的不降子序列,并把峰顶的人分到橘子取更大值,其余同上
{
if(a[i]<a[i-1])t[i-1]=max(t[i-1],t[i]+1);
if(a[i-1]==a[i])t[i-1]=t[i];
}
for(int i=1;i<=n;i++)ans+=t[i];//统计
cout<<ans;//输出
}
私のACコード
#include <iostream>
#include <cstdio>
#include <algorithm>
#define SIZE (int)1e6 + 10
#define ll long long
using namespace std;
int a[SIZE], b[SIZE];
void f1(const int &);
void f2(const int &);
int main() {
freopen("cpp.in", "r", stdin);
freopen("cpp.out", "w", stdout);
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
b[i] = 1;
}
f1(n);
f2(n);
ll ans = 0;
for (int i = 1; i <= n; ++i) {
ans += b[i];
}
printf("%lld\n", ans);
return 0;
}
void f1(const int &n) {
for (int i = 2; i <= n; ++i) {
if (a[i] > a[i - 1]) {
b[i] = b[i - 1] + 1;
}
if (a[i] == a[i - 1]) {
b[i] = b[i - 1];
}
}
}
void f2(const int &n) {
for (int i = n - 1; i >= 1; --i) {
if (a[i] > a[i + 1]) {
b[i] = max(b[i], b[i + 1] + 1);
}
if (a[i] == a[i + 1]) {
b[i] = b[i + 1];
}
}
}