题目 | Least Elements
AtCoder Beginner Contest 281
E - Least Elements
https://atcoder.jp/contests/abc281/tasks/abc281_e
Time Limit: 2 sec / Memory Limit: 1024 MB
Score :
Problem Statement
You are given an integer sequence
For each
Find the sum of the firstvalues in the sorted list of the integers in ascending order.
Constraints
- All values in the input are integers.
Input
The input is given from Standard Input in the following format:
Output
Let
Sample Input 1
6 4 3
3 1 4 1 5 9
Sample Output 1
5 6 10
- For
, sorting in ascending order yields , where the sum of the first three values is . - For
, sorting in ascending order yields , where the sum of the first three values is . - For
, sorting in ascending order yields , where the sum of the first three values is .
Sample Input 2
10 6 3
12 2 17 11 19 8 4 3 6 20
Sample Output 2
21 14 15 13 13
题解
该题算是一种滑动窗口,如果我们在每次滑动窗口时,都进行排序、累加求和,那么肯定是不符合时间限制的。
首先需要意识到,窗口每次滑动时,两次的结果是有某种关联的,我们应该找滑动时的变化规律,而不是每次重新计算。
维护内容
我们维护两个多重集合
的大小为 ,储存长度为 的滑窗中,最小的 个元素。 中元素之和 即为我们需要的答案。 的大小为 ,储存滑窗中剩余的元素。
初始化
首先需要初始化
变化规律
我们的滑动窗口向右移动一位,将会造成一个元素离开和一个元素加入,我们分别记为
对
且 且 且 且
情况一:
离开和加入的元素均比
情况二:
离开和加入的元素均比
情况三:
离开的元素比
情况四:
离开的元素比
特殊情况
我们上面的分类是假定了
例如
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int N, M, K;
cin >> N >> M >> K;
vector<int> A(N);
for (int i = 0; i < N; i++)
cin >> A[i];
multiset<int> l, r;
int sum = 0;
// 初始化l,r,sum的值
for (int i = 0; i < M; i++)
l.insert(A[i]);
while (l.size() > K)
{
int mx = *l.rbegin();
r.insert(mx);
l.extract(mx);
}
for (auto &elem : l)
sum += elem;
cout << sum << ' ';
// 开始递推接下来的值
for (int i = 1; i + M - 1 < N; i++)
{
int out = A[i - 1], in = A[i + M - 1];
int lmax = *l.rbegin(), rmin = *r.begin();
if (r.empty())
{
l.extract(out);
l.insert(in);
sum += in - out;
}
else if (out > lmax && in > lmax)
{
r.extract(out);
r.insert(in);
}
else if (out < rmin && in < rmin)
{
l.extract(out);
l.insert(in);
sum += in - out;
}
else if (out < rmin && in > lmax)
{
r.insert(in);
int new_rmin = *r.begin();
r.extract(new_rmin);
l.insert(new_rmin);
l.extract(out);
sum += new_rmin - out;
}
else // if (out > lmax && in < rmin)
{
l.insert(in);
int new_lmax = *l.rbegin();
l.extract(new_lmax);
r.insert(new_lmax);
r.extract(out);
sum += in - new_lmax;
}
cout << sum << ' ';
}
cout << endl;
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi