C ++
 Computer >> コンピューター >  >> プログラミング >> C ++

C++でのサブアレイの最小値の合計


整数Aの配列があるとします。min(B)の合計を見つける必要があります。ここで、BはAのすべての(連続した)サブ配列にまたがっています。大きい場合は、モジュロ10 ^ 9 + 7で答えを返します。したがって、入力が[3,1,2,4]の場合、サブ配列は[3]、[1]、[であるため、出力は17になります。 2]、[4]、[3,1]、[1,2]、[2,4]、[3,1,2]、[1,2,4]、[3,1,2,4] 、したがって、最小値は[3,1,2,4,1,1,2,1,1,1]であり、合計は17です。

これを解決するには、次の手順に従います-

  • m:=1 x 10 ^ 9 + 7

  • 2つのメソッドを定義します。add()はa、bを取り、(a mod m + b mod m)mod mを返し、mul()はa、bを取り、(a mod m * b mod m)modm<を返します。 / P>

  • mainメソッドは、配列Aを取得し、スタックstを定義し、n:=配列Aのサイズを設定します

  • サイズnの左側に2つの配列を定義し、-1で埋め、もう1つはサイズnの右側にあり、nで埋めます

  • ans:=0

    を設定します
  • 0からn–1の範囲のiの場合

    • stが空ではなく、A [stack top]> =A [i]の場合、stから削除します

    • stが空でない場合は、left [i]:=top of st

      を設定します。
    • iをstに挿入

  • stが空でない場合は、stを削除します

  • n –1から0までの範囲のiの場合

    • stが空ではなく、A [stack top]> =A [i]の場合、stから削除します

    • stが空でない場合は、right [i]:=top of st

      を設定します。
    • iをstに挿入

  • 0からn–1の範囲のiの場合

    • leftBound:=i – left [i] + 1、rightBound:=right [i] – 1 – i

    • contri:=1 + leftBound + rightBound +(leftBound * rightBound)

    • ans:=add(ans and mul(contri、A [i]))

  • ansを返す

例(C ++)

理解を深めるために、次の実装を見てみましょう-

#include <bits/stdc++.h>
using namespace std;
typedef long long int lli;
const lli MOD = 1e9 + 7;
class Solution {
public:
   lli add(lli a, lli b){
      return (a % MOD + b % MOD) % MOD;
   }
   lli mul(lli a, lli b){
      return (a % MOD * b % MOD) % MOD;
   }
   int sumSubarrayMins(vector<int>& A) {
      stack <int> st;
      int n = A.size();
      vector <int> left(n, -1);
      vector <int> right(n, n);
      int ans = 0;
      for(int i = 0; i < n; i++){
         while(!st.empty() && A[st.top()] >= A[i]){
         st.pop();
      }
      if(!st.empty())left[i] = st.top();
         st.push(i);
      }
      while(!st.empty())st.pop();
      for(int i = n - 1; i >= 0; i--){
         while(!st.empty() && A[st.top()] > A[i]){
            st.pop();
         }
         if(!st.empty())right[i] = st.top();
            st.push(i);
      }
      for(int i = 0; i < n; i++){
         int leftBound = i - (left[i] + 1);
         int rightBound = (right[i] - 1) - i;
         int contri = 1 + leftBound + rightBound + (leftBound * rightBound);
         ans = add(ans, mul(contri, A[i]));
      }
      return ans;
   }
};
main(){
   vector<int> v = {3,1,2,4};
   Solution ob;
   cout << (ob.sumSubarrayMins(v));
}

入力

[3,1,2,4]

出力

17

  1. C ++のプレフィックス合計を使用したO(n)の最大サブ配列合計

    問題の説明 正の整数と負の整数の配列が与えられた場合、その配列の最大サブ配列の合計を求めます 例 入力配列が− {-12、-5、4、-1、-7、1、8、-3}の場合、出力は9 アルゴリズム 入力配列のプレフィックス合計を計算します。 Initialize− min_prefix_sum =0、res =-infinite i=0からnまでのループを維持します。 (nは入力配列のサイズです。) cand =prefix_sum [i] – mini キャンドの場合 がres(これまでのサブアレイの最大合計)より大きい場合は、resをcandで更新します。

  2. C ++でのアリコートの合計?

    ここで、アリコートの合計は何ですか? nのアリコート和は、nを除くnのすべての完全な因子の合計です。たとえば、数値が20の場合、完全な因数は(1、2、4、5、10)です。したがって、アリコートの合計は22です。 興味深い事実の1つは、ある数のアリコートの合計がその数そのものである場合、その数は完全数であるということです。たとえば、6。係数は(1、2、3)です。アリコートの合計は1+2 + 3=6です。 次のアルゴリズムを使用してアリコートの合計を取得する方法を見てみましょう。 アルゴリズム getAliquotSum(n) begin    sum := 0 &nbs