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

C++の特定の範囲の最大プレフィックス合計


問題の説明

n個の整数とq個のクエリの配列が与えられた場合、各クエリの範囲はlからrです。 l –rの範囲の最大プレフィックス合計を見つけます。

If input array is arr[] = {-1, 2, 3, -5} and
queries = 2 and ranges are:
l = 0, r = 3
l = 1, r = 3 then output will be 4 and 5.
  • 最初のクエリの範囲(0、3)は[-1、2、3、-5]です。これはプレフィックスであるため、-1から開始する必要があります。したがって、プレフィックスの最大合計は-1 + 2 + 3=4になります
  • 2番目のクエリの範囲(1、3)は[2、3、-5]です。これはプレフィックスであるため、2から開始する必要があります。したがって、プレフィックスの最大合計は2 + 3 =5<になります。 / li>

アルゴリズム

  • 各ノードが2つの値s(sumとprefix_sum)を格納するセグメントツリーを構築し、そのノードに対して範囲クエリを実行して、最大プレフィックス合計を見つけます。
  • 最大プレフィックス合計を見つけるには、2つのものが必要になります。1つは合計で、もう1つはプレフィックス合計です
  • マージすると、範囲の合計と、セグメントツリーにmax(prefix.left、prefix.sum + prefix.right)を格納するプレフィックスの合計の2つが返されます。
  • 任意の2つの範囲を組み合わせた場合の最大プレフィックス合計は、左側からのプレフィックス合計または左側の合計+右側のプレフィックス合計のいずれか大きい方が考慮されます。

#include <bits/stdc++.h>
using namespace std;
typedef struct node {
   int sum;
   int prefix;
} node;
node tree[4 * 10000];
void build(int *arr, int idx, int start, int end) {
   if (start == end) {
      tree[idx].sum = arr[start];
      tree[idx].prefix = arr[start];
   } else {
      int mid = (start + end) / 2;
      build(arr, 2 * idx + 1, start, mid);
      build(arr, 2 * idx + 2, mid + 1, end);
      tree[idx].sum = tree[2 * idx + 1].sum + tree[2 *
      idx + 2].sum;
      tree[idx].prefix = max(tree[2 * idx + 1].prefix,
      tree[2 * idx + 1].sum + tree[2 * idx + 2].prefix);
   }
}
node query(int idx, int start, int end, int l, int r) {
   node result;
   result.sum = result.prefix = -1;
   if (start > r || end < l) {
      return result;
   }
   if (start >= l && end <= r) {
      return tree[idx];
   }
   int mid = (start + end) / 2;
   if (l > mid) {
      return query(2 * idx + 2, mid + 1, end, l, r);
   }
   if (r <= mid) {
      return query(2 * idx + 1, start, mid, l, r);
   }
   node left = query(2 * idx + 1, start, mid, l, r);
   node right = query(2 * idx + 2, mid + 1, end, l, r);
   result.sum = left.sum + right.sum;
   result.prefix = max(left.prefix, left.sum + right.prefix);
   return result;
}
int main() {
   int arr[] = { -2, -3, 4, -1, -2, 1, 5, -3 };
   int n = sizeof(arr) / sizeof(arr[0]);
   build(arr, 0, 0, n - 1);
   cout << "Result = " << query(0, 0, n - 1, 3, 5).prefix
   << endl;
   return 0;
}

出力

上記のプログラムをコンパイルして実行する場合。次の出力を生成します-

Result = -1

  1. C++で指定された範囲からの最大ビットごとのANDペア

    問題の説明 範囲[L、R]が与えられた場合、タスクは、L≤X

  2. 更新なしの範囲合計クエリ用のC++プログラム?

    ここでは、配列内のインデックスiからインデックスjまでの要素の合計を取得する方法を説明します。これは基本的に範囲クエリです。インデックスiからjまで1つのループを実行し、合計を計算するだけで、タスクは簡単です。ただし、この種の範囲クエリが複数回実行されることに注意する必要があります。したがって、上記の方法を使用すると、かなりの時間がかかります。より効率的な方法を使用してこの問題を解決するには、最初に累積合計を取得し、次に範囲合計を一定時間で見つけることができます。アイデアを得るためのアルゴリズムを見てみましょう。 アルゴリズム rangeSum(arr、i、j) begin   &