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가 됩니다.
  • 두 번째 쿼리의 범위 (1, 3)은 [2, 3, -5]입니다. 접두사이므로 2부터 시작해야 합니다. 따라서 최대 접두사 합계는 2 + 3 =5

알고리즘

  • 각 노드가 두 개의 값 s(sum 및 prefix_sum)를 저장하는 세그먼트 트리를 만들고 최대 접두사 합계를 찾기 위해 범위 쿼리를 수행합니다.
  • 최대 접두사 합을 찾으려면 두 가지가 필요합니다. 하나는 합이고 다른 하나는 접두사 합입니다.
  • 병합은 범위의 합과 세그먼트 트리에 max(prefix.left, prefix.sum + prefix.right)를 저장할 접두사 합이라는 두 가지를 반환합니다.
  • 두 범위 결합에 대한 최대 접두사 합계는 왼쪽의 접두사 합계 또는 왼쪽의 접두사 합계 + 오른쪽의 접두사 합계 중 최대값이 고려됩니다.

예시

#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