# | 제출 시각 | 아이디 | 문제 | 언어 | 결과 | 실행 시간 | 메모리 |
---|---|---|---|---|---|---|---|
372333 | toitoi | 수열 (APIO14_sequence) | C++14 | 1259 ms | 82900 KiB |
이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
using namespace std;
class SeqGame {
typedef pair<int, int64_t> Line;
private:
vector<int64_t> sum;
vector<int64_t> points;
vector<vector<int>> log;
deque<Line> convhull;
void split();
void update_convhull(Line line);
Line query_convhull(int64_t x);
int64_t intersec(Line line1, Line line2);
public:
SeqGame(vector<int> seq);
pair<int64_t, vector<int>> get_max_point(int k);
};
SeqGame::SeqGame(vector<int> seq) {
int n = seq.size();
sum.resize(n);
sum[0] = seq[0];
for (int i = 1; i < n; i++) {
sum[i] = seq[i] + sum[i - 1];
}
}
pair<int64_t, vector<int>> SeqGame::get_max_point(int k) {
for (int i = 0; i < k; i++) {
split();
}
int64_t max_point = -1;
int max_point_idx = 0;
vector<int> max_point_log;
for (int i = k - 1; i < points.size() - 1; i++) {
if (max_point < points[i]) {
max_point = points[i];
max_point_idx = i;
}
}
max_point_log.push_back(max_point_idx);
for (int k = log.size() - 1; k >= 0; k--) {
max_point_idx = log[k][max_point_idx];
max_point_log.push_back(max_point_idx);
}
reverse(max_point_log.begin(), max_point_log.end());
return {max_point, max_point_log};
}
void SeqGame::split() {
int n = sum.size();
int k = log.size();
if (points.empty()) {
points.resize(n);
for (int i = 0; i < n - 1; i++) {
points[i] = sum[i] * (sum[n - 1] - sum[i]);
}
return;
}
vector<int64_t> new_points(n);
vector<int> new_log(n);
for (int i = k + 1; i < n - 1; i++) {
update_convhull({i - 1, points[i - 1] - sum[n - 1] * sum[i - 1]});
auto res = query_convhull(sum[i]);
int j = res.first;
new_points[i] = res.second + (sum[j] + sum[n - 1] - sum[i]) * sum[i];
new_log[i] = j;
}
points = new_points;
log.push_back(new_log);
convhull.clear();
}
pair<int, int64_t> SeqGame::query_convhull(int64_t x) {
while (convhull.size() >= 2) {
if (intersec(convhull[0], convhull[1]) <= x) {
convhull.pop_front();
} else {
break;
}
}
return convhull.front();
}
void SeqGame::update_convhull(Line line) {
if (convhull.empty()) {
convhull.push_back(line);
return;
}
while (convhull.size() >= 2) {
int n = convhull.size();
if (intersec(convhull[n - 2], convhull[n - 1]) >=
intersec(convhull[n - 1], line)) {
convhull.pop_back();
} else {
break;
}
}
if (sum[convhull.back().first] != sum[line.first]) {
convhull.push_back(line);
} else {
if (convhull.back().second < line.second) {
convhull.pop_back();
convhull.push_back(line);
}
}
}
int64_t SeqGame::intersec(Line line1, Line line2) {
int64_t a = sum[line1.first] - sum[line2.first];
int64_t b = line2.second - line1.second;
if (a == 0) {
return (1LL << 62);
} else if (b % a == 0) {
return b / a;
} else {
return b / a + 1;
}
}
int main() {
int n, k;
scanf("%d %d", &n, &k);
vector<int> seq(n);
for (int i = 0; i < n; i++) {
scanf("%d", &seq[i]);
}
auto game = SeqGame(seq);
auto ans = game.get_max_point(k);
printf("%lld\n", ans.first);
for (int i = 0; i < ans.second.size(); i++) {
printf("%d ", ans.second[i] + 1);
}
return 0;
}
컴파일 시 표준 에러 (stderr) 메시지
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |