問題:
配列シーケンスが与えられた場合、次のように計算されたすべての間隔の中で間隔が最大値になるように間隔を選択する必要があります。
間隔内の最小数*間隔内のすべての数と最終プログラムの合計が計算された最大値を出力します。特定の間隔は必要ありません。与えられたシーケンス[62 1]について、上記の式に従って、各間隔で選択できるすべての計算値を取得できます:
[6] = 6 * 6 = 36;
[2] = 2 * 2 = 4;
[1] = 1 * 1 = 1;
[6,2] = 2 * 8 = 16;
[2,1] = 1 * 3 = 3;
[6、2、1] = 1 * 9 = 9;
上記の計算から、選択した間隔[6]、計算値は36、プログラム出力は36であることがわかります。
間隔内のすべての数値は[0、100]の範囲です。
入る:
第一行输入数组序列长度n,第二行输入数组序列。
对于 50%的数据, 1 <= n <= 10000;
对于 100%的数据, 1 <= n <= 500000;
出力:
输出数组经过计算后的最大值。
例:
输入
3
6 2 1
输出
36
分析:
この質問の最も簡単なアイデアは、現在の要素を間隔全体で最小の数と見なすことです。間隔では、この要素の左側のすべての要素と右側のすべての要素がこの要素よりも大きくなります。
したがって、問題は次のように変換されます
。1。配列全体をトラバースします
。2 。トラバースするときは、この要素よりも大きい要素xの最初の要素LとRを左右に探します。3
。これの計算値間隔がx * sum(L + 1、R-1)に等しい場合は、最大値を探します
コード:
#include <iostream>
#include <numeric>
using namespace std;
//局部变量存在栈区,无法存储这么大数组
int arr[500005];
int main()
{
int n,max=0;
cin >> n;
for(int i=0;i<n;i++)
{
cin >> arr[i];
}
//开始遍历数组
for(int i=0;i<n;i++)
{
int min = arr[i];
//寻找最左值
int L = i - 1;
while (L>=0)
{
if(arr[L]>=min)
{
L--;
}
else
{
break;
}
}
//别忘了加1
L++;
//寻找最右值
int R = i + 1;
while (R<n)
{
if (arr[R] >= min)
{
R++;
}
else
{
break;
}
}
//别忘了减1
R--;
//求和
int sum = accumulate(arr+L,arr+R+1, 0);
//更新最大值
max = (max > sum * min) ? max : sum * min;
}
cout << max;
return 0;
}
Accumulate()関数については、https://blog.csdn.net/weixin_43919932/article/details/113354255を参照して説明してください。
注:
トピックのトラバーサルプロセス全体で、明らかに時間計算量はn ^ 2に近くなります。nが非常に大きくなると、非常に時間がかかります。プログラマーは、資本家のようにコンピューターのすべてのリソースを絞り込んで、自分のコードの効率を向上させる必要があるということわざがあります(まあ、私は言いました)。ここに上司の解決策の説明があります。
問題では、nの値は非常に大きくなる可能性があります(1 <= n <= 500000)が、パラメーターの1つは短い間隔で維持され、各要素の値である最大値の比較が含まれます。範囲(0 <= x <= 100)。
外側のループでは、最小間隔を決定することが重要な作業であるため、間隔Nと間隔Xは交換可能であるように見えます。
コード:
#include <iostream>
using namespace std;
//局部变量存在栈区,无法存储这么大数组
int arr[500005];
int main()
{
int n,max=0;
cin >> n;
for(int i=0;i<n;i++)
{
cin >> arr[i];
}
//arr[n]=0是为方便计算最后一节区间的计算值'
arr[n] = 0;
//假设有数组X[i],表示在数组arr中,元素都大于i的子区间的题目所需求的最大值,不过在只是求最大值的情况下这个数组可以省略
for(int j=100;j>=1;j--)
{
int sum = 0;//临时存储和
int min = j;//子区间最小值
//对数组进行遍历,一次遍历我们可以找出多个区间
for(int i=0;i<=n;i++)
{
//满足条件,则开始分割子区间
if(arr[i]>=j)
{
sum += arr[i];
min = (min < arr[i]) ? min : arr[i];
}
//不满足条件,子区间断开,计算子区间的值并更新最大值,但此时仍继续遍历,寻找下一个满足子区间
else
{
max = (max > sum * min) ? max : sum * min;
sum = 0;
min = j;
}
}
}
cout << max;
return 0;
}