이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
/**
_ _ __ _ _ _ _ _ _
|a ||t ||o d | |o |
| __ _| | _ | __| _ |
| __ |/_ | __ /__\ / _\|
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const int N_MAX = 2000000;
const ll INF = LLONG_MAX;
const ld EPS = 1e-9;
int N, K;
int A[N_MAX + 2];
struct SegInfo {
ll first; int rate;
};
SegInfo seg_tree[N_MAX * 4 + 2];
void build (int node, int l, int r) {
seg_tree[node] = SegInfo{0, 0};
if (l == r) {
return;
}
int mid = (l + r) / 2;
int left = node * 2, right = node * 2 + 1;
build(left, l, mid);
build(right, mid + 1, r);
}
void build () {
build(1, 1, N);
}
void split (int node, int l, int r) {
int mid = (l + r) / 2;
int left = node * 2, right = node * 2 + 1;
seg_tree[left].first += seg_tree[node].first + (ll) (r - mid) * seg_tree[node].rate;
seg_tree[left].rate += seg_tree[node].rate;
seg_tree[right].first += seg_tree[node].first;
seg_tree[right].rate += seg_tree[node].rate;
seg_tree[node].first = seg_tree[node].rate = 0;
}
void update (int node, int l, int r, int pos, ll first) {
if (r <= pos) {
seg_tree[node].first += first + (pos - r);
seg_tree[node].rate++;
return;
}
split(node, l, r);
int mid = (l + r) / 2;
int left = node * 2, right = node * 2 + 1;
update(left, l, mid, pos, first);
if (mid + 1 <= pos) {
update(right, mid + 1, r, pos, first);
}
}
void update (int pos, int first) {
update(1, 1, N, pos, first);
}
ll query (int node, int l, int r, int pos) {
if (l == r) {
return seg_tree[node].first;
}
split(node, l, r);
int mid = (l + r) / 2;
int left = node * 2, right = node * 2 + 1;
if (pos <= mid) {
return query(left, l, mid, pos);
} else {
return query(right, mid + 1, r, pos);
}
}
ll query (int pos) {
return query(1, 1, N, pos);
}
ld dp[N_MAX + 2];
int cnt[N_MAX + 2];
pair <ld, int> f (int j) {
return make_pair(dp[j] + query(j + 1), cnt[j]);
}
ll solve (ld pen) {
build();
deque <int> rel;
for (int i = 1; i <= N; i++) {
if (A[i] - i + 1 <= i) {
update(A[i] - i + 1, 0);
} else {
update(i, (A[i] - i + 1) - i);
}
while (rel.empty() == false && f(i - 1) <= f(rel.back())) {
rel.pop_back();
}
rel.push_back(i - 1);
while ((int) rel.size() >= 2 && f(rel[0]) >= f(rel[1])) {
rel.pop_front();
}
if (rel.empty() == true) {
dp[i] = INF;
} else {
tie(dp[i], cnt[i]) = f(rel.front());
dp[i] += pen; cnt[i]++;
}
}
return (ll) round(dp[N] - pen * cnt[N]);
}
int main () {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout << fixed << setprecision(2);
cin >> N >> K;
string S;
cin >> S;
for (int i = 0, j = 0; i < N * 2; i++) {
if (S[i] == 'A') {
A[++j] = i + 1;
}
}
ld l = 0, r = LLONG_MAX; int iter = 200;
while (l + EPS < r) {
ld mid = (l + r) / 2;
solve(mid);
if (cnt[N] <= K) {
r = mid;
} else {
l = mid + EPS;
}
}
cout << solve(l) << "\n";
assert(cnt[N] <= K);
return 0;
}
컴파일 시 표준 에러 (stderr) 메시지
chorus.cpp: In function 'int main()':
chorus.cpp:133:34: warning: unused variable 'iter' [-Wunused-variable]
133 | ld l = 0, r = LLONG_MAX; int iter = 200;
| ^~~~
# | 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... |