C. Little Girl and Maximum Sum
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
The little girl loves the problems on array queries very much.
One day she came across a rather well-known problem: you've got an array of n elements (the elements of the array are indexed starting from 1); also, there are q queries, each one is defined by a pair of integers li, ri (1 ≤ li ≤ ri ≤ n). You need to find for each query the sum of elements of the array with indexes from li to ri, inclusive.
The little girl found the problem rather boring. She decided to reorder the array elements before replying to the queries in a way that makes the sum of query replies maximum possible. Your task is to find the value of this maximum sum.
Input
The first line contains two space-separated integers n (1 ≤ n ≤ 2·105) and q (1 ≤ q ≤ 2·105) — the number of elements in the array and the number of queries, correspondingly.
The next line contains n space-separated integers ai (1 ≤ ai ≤ 2·105) — the array elements.
Each of the following q lines contains two space-separated integers li and ri (1 ≤ li ≤ ri ≤ n) — the i-th query.
Output
In a single line print a single integer — the maximum sum of query replies after the array elements are reordered.
Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.
<코드>
#include <iostream>
#include <algorithm>
using namespace std;
int n, q;
int l, r;
int arr[200001];
int index[200001];
long long sum = 0;
int main()
{
scanf("%d %d", &n, &q);
for (int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
for (int i = 0; i < q; i++)
{
scanf("%d %d", &l, &r);
index[l - 1] += 1;
index[r] -= 1;
}
for (int i = 1; i < n; i++)
{
index[i] += index[i - 1];
}
sort(arr, arr + n);
sort(index, index + n);
for (int i = 0; i < n; i++)
{
sum += (long long)arr[i] * (long long)index[i];
}
printf("%I64d\n", sum);
}
이 문제는 배열 요소마다 값이 있고 구간 합들이 주어지면 배열 요소들을 순서를 바꿔서 구간 합의 최대값을 찾는 문제입니다. 기본적인 풀이는 인덱스 트리를 활용하여 풀 수 있는데 아직 인덱스트리에 대해 개념이 잡히지 않은 상태여서 구간 합들을 일일이 더해주는 식의 코드를 짜보았습니다.
<변경 전>
for (int i = 0; i < q; i++)
{
scanf("%d %d", &l, &r);
for (int j = l - 1; j < r; j++)
{
index[j]++;
}
}
<변경 후>
for (int i = 0; i < q; i++)
{
scanf("%d %d", &l, &r);
index[l - 1] += 1;
index[r] -= 1;
}
for (int i = 1; i < n; i++)
{
index[i] += index[i - 1];
}
변경 전 코드는 이중 for문으로, 시간복잡도가 O(N²)이 되어 시간 초과가 발생하므로
구간의 시작 인덱스와 끝+1 인덱스에 각각 +1 과 -1 을 해주고 index[i] += index[i - 1]; 식으로 prefix sum을 해주면 구간들에 각각 +1을 더해준 효과를 내어 시간복잡도가 O(N²)를 피할 수 있습니다.
https://codeforces.com/problemset/problem/276/C
'🧩PS > 🥈Nomal' 카테고리의 다른 글
[C/C++] Codeforce 522A - Reposts(DFS) (0) | 2020.06.09 |
---|---|
[C/C++] Codeforce 219D - Choosing Capital for Treeland (0) | 2020.06.09 |
[C/C++] 백준 15649번 - N과 M (1) (DFS, 백트래킹) (0) | 2020.06.06 |
[C/C++] 백준 2606번 바이러스(BFS/플로이드 와샬 알고리즘) (0) | 2020.06.06 |
[C/C++] 백준 4411번 The Trip (0) | 2020.05.30 |