1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int n, st, d;
vector<ll> raw_values;
vector<int> a; // compressed indices per city
vector<ll> cmp; // sorted unique values
vector<char> active_flag; // whether index i is active in the current structure
ll ans = 0;
struct Segtree {
vector<ll> seg;
vector<int> cnt;
int m = 0;
void allocate(int size) {
m = size;
seg.assign(4 * m + 5, 0);
cnt.assign(4 * m + 5, 0);
}
void clear() {
fill(seg.begin(), seg.end(), 0);
fill(cnt.begin(), cnt.end(), 0);
}
void upd(int now, int s, int e, int i, int v) {
if (i < s || i > e) return;
cnt[now] += v;
seg[now] += (ll)v * cmp[i];
if (s == e) return;
int mid = (s + e) >> 1;
upd(now << 1, s, mid, i, v);
upd(now << 1 | 1, mid + 1, e, i, v);
}
// Sum of the largest k values among active elements
ll sum_max_kth(int now, int s, int e, int k) {
if (k <= 0 || cnt[now] == 0) return 0LL;
if (k >= cnt[now]) return seg[now];
if (s == e) return (ll)k * cmp[s];
int mid = (s + e) >> 1;
int right_count = cnt[now << 1 | 1];
if (right_count >= k) {
return sum_max_kth(now << 1 | 1, mid + 1, e, k);
} else {
return seg[now << 1 | 1] + sum_max_kth(now << 1, s, mid, k - right_count);
}
}
} S;
void toggle_idx(int i, int v) { // v: +1 (add) or -1 (remove)
bool want_on = (v == 1);
if ((active_flag[i] != 0) == want_on) return;
active_flag[i] ^= 1;
S.upd(1, 0, (int)cmp.size() - 1, a[i], v);
}
ll qry(int k) {
if (k <= 0) return 0;
return S.sum_max_kth(1, 0, (int)cmp.size() - 1, k);
}
// Divide & conquer over l in [s,e], with feasible r in [kmin,kmax]
void dnc(int s, int e, int kmin, int kmax) {
if (s > e) return;
int m = (s + e) >> 1;
// Ensure [m..e] is active
for (int i = m; i <= e; i++) toggle_idx(i, +1);
int klim = min(kmax, 2 * m + d - st); // feasibility cap for r
ll best_local = 0;
int best_r = kmin;
for (int i = kmin; i <= klim; i++) {
toggle_idx(i, +1);
// k = d - (st - m) - (i - m)
ll tmp = qry(d - (st - m) - (i - m));
if (tmp > best_local) {
best_local = tmp;
best_r = i;
}
}
ans = max(ans, best_local);
// Roll back [best_r..klim]
for (int i = klim; i >= best_r; i--) toggle_idx(i, -1);
// Recurse right half
if (m < e) {
int mm = (m + 1 + e) >> 1;
for (int i = m; i <= mm; i++) toggle_idx(i, -1);
dnc(m + 1, e, best_r, kmax);
}
// Fully roll back r-range additions
for (int i = kmax; i >= kmin; i--) toggle_idx(i, -1);
// Recurse left half
if (s < m) {
int ss = (s + m - 1) >> 1;
for (int i = m; i < min(kmin, e + 1); i++) toggle_idx(i, +1);
dnc(s, m - 1, kmin, best_r);
for (int i = ss; i <= e; i++) toggle_idx(i, -1);
}
// Roll back [m..e]
for (int i = m; i <= e; i++) toggle_idx(i, -1);
}
void solve_one_direction() {
S.clear();
fill(active_flag.begin(), active_flag.end(), 0);
int l = max(0, st - d);
dnc(l, st, st, n - 1);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
if (!(cin >> n >> st >> d)) return 0;
raw_values.resize(n);
for (int i = 0; i < n; i++) cin >> raw_values[i];
// Coordinate compression
cmp = raw_values;
sort(cmp.begin(), cmp.end());
cmp.erase(unique(cmp.begin(), cmp.end()), cmp.end());
a.resize(n);
for (int i = 0; i < n; i++) {
a[i] = int(lower_bound(cmp.begin(), cmp.end(), raw_values[i]) - cmp.begin());
}
S.allocate((int)cmp.size());
active_flag.assign(n, 0);
// Left-then-right case
solve_one_direction();
// Right-then-left case by reversing
reverse(a.begin(), a.end());
st = n - 1 - st;
solve_one_direction();
cout << ans << '\n';
return 0;
}
|