이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#ifndef FEXT
#include "holiday.h"
#endif
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define endl '\n'
#define fi first
#define se second
#define For(i, l, r) for (auto i = (l); i < (r); i++)
#define ForE(i, l, r) for (auto i = (l); i <= (r); i++)
#define FordE(i, l, r) for (auto i = (l); i >= (r); i--)
#define Fora(v, a) for (auto v: (a))
#define bend(a) (a).begin(), (a).end()
#define isz(a) ((signed)(a).size())
using ll = long long;
using ld = long double;
using pii = pair <int, int>;
using vi = vector <int>;
using vpii = vector <pii>;
using vvi = vector <vi>;
struct segment_tree{
pair <int, ll> seg[1 << 18];
void build(int id, int l, int r){
if (l == r){
seg[id] = make_pair(0, 0);
return;
}
int mid = (l + r) >> 1;
build(id * 2, l, mid);
build(id * 2 + 1, mid + 1, r);
seg[id] = make_pair(0, 0);
}
void update(int id, int l, int r, int i, int val){
if (l == r){
seg[id].fi++;
seg[id].se += val;
return;
}
int mid = (l + r) >> 1;
if (i <= mid){
update(id * 2, l, mid, i, val);
}
else{
update(id * 2 + 1, mid + 1, r, i, val);
}
seg[id] = make_pair(seg[id * 2].fi + seg[id * 2 + 1].fi, seg[id * 2].se + seg[id * 2 + 1].se);
}
ll sum_max(int id, int l, int r, int x){
if (x >= seg[id].fi){
return seg[id].se;
}
if (l == r or x <= 0){
return 0;
}
int mid = (l + r) >> 1;
if (seg[id * 2 + 1].fi > x){
return sum_max(id * 2 + 1, mid + 1, r, x);
}
else{
return sum_max(id * 2, l, mid, x - seg[id * 2 + 1].fi) + seg[id * 2 + 1].se;
}
}
} seg;
const int N = 1e5 + 5, M = 3e5 + 5;
#define left __left__
#define right __right__
int left[N], right[N];
pair <int, ll> ansleft[M], ansright[M];
int pos[N];
int idxopt;
void dnc(int n, int a[], pair <int, ll> ans[], int l, int r, int optl, int optr, queue <tuple <int, int, int, int>> &qu){
int mid = (l + r) >> 1;
ans[mid] = make_pair(-1, 0);
if (optl < idxopt){
seg.build(1, 0, n - 1);
idxopt = 0;
seg.update(1, 0, n - 1, pos[idxopt], a[idxopt]);
}
ForE(opt, optl, optr){
while (idxopt < opt){
idxopt++;
seg.update(1, 0, n - 1, pos[idxopt], a[idxopt]);
}
ll val = seg.sum_max(1, 0, n - 1, mid - opt);
if (ans[mid].fi == -1 or ans[mid].se < val){
ans[mid] = make_pair(opt, val);
}
}
// if (mid < 10){
// cout << "dnc " << l << ' ' << r << ' ' << mid << ' ' << ans[mid].fi << ' ' << ans[mid].se << endl;
// }
if (l < mid){
qu.emplace(l, mid - 1, optl, ans[mid].fi);
}
if (mid < r){
qu.emplace(mid + 1, r, ans[mid].fi, optr);
}
}
void findMaxAttractionStart1(int n, int a[], pair <int, ll> ans[]){
// cout << "findMaxAttractionStart1 " << n << endl;
// For(i, 0, n){
// cout << a[i] << ' ';
// } cout << endl;
{
vpii b;
For(i, 0, n){
b.emplace_back(a[i], i);
}
sort(bend(b));
For(i, 0, n){
pos[b[i].se] = i;
}
}
idxopt = n;
queue <tuple <int, int, int, int>> qu;
qu.emplace(0, 2 * n, 0, n - 1);
while (!qu.empty()){
int l, r, optl, optr; tie(l, r, optl, optr) = qu.front(); qu.pop();
dnc(n, a, ans, l, r, optl, optr, qu);
}
For(i, 2 * n + 1, M){
ans[i] = ans[i - 1];
}
// For(i, 0, 10){
// cout << i << ' ' << ans[i].fi << ' ' << ans[i].se << endl;
// }
}
ll findMaxAttraction(int n, int start, int d, int a[]){
ll ans = 0;
FordE(i, start, 0){
left[start - i] = a[i];
}
findMaxAttractionStart1(start + 1, left, ansleft);
ForE(dl, 0, d){
ans = max(ans, ansleft[dl].se);
}
if (start < n - 1){
For(i, start + 1, n){
right[i - start - 1] = a[i];
}
findMaxAttractionStart1(n - start - 1, right, ansright);
ForE(dl, 0, d){
int dr = d - dl - ansleft[dl].fi - 1;
if (!(0 <= dr and dr <= d)){
continue;
}
// cout << "dl dr left " << dl << ' ' << dr << endl;
// cout << ansleft[dl].fi << ' ' << ansleft[dl].se << ' ' << ansright[dr].fi << ' ' << ansright[dr].se << endl;
ans = max(ans, ansleft[dl].se + ansright[dr].se);
}
}
For(i, start, n){
right[i - start] = a[i];
}
findMaxAttractionStart1(n - start, right, ansright);
ForE(dr, 0, d){
ans = max(ans, ansright[dr].se);
}
if (start > 0){
FordE(i, start - 1, 0){
left[start - 1 - i] = a[i];
}
findMaxAttractionStart1(start, left, ansleft);
ForE(dr, 0, d){
int dl = d - dr - ansright[dr].fi - 1;
if (!(0 <= dl and dl <= d)){
continue;
}
// cout << "dl dr right " << dl << ' ' << dr << endl;
// cout << ansleft[dl].fi << ' ' << ansleft[dl].se << ' ' << ansright[dr].fi << ' ' << ansright[dr].se << endl;
ans = max(ans, ansleft[dl].se + ansright[dr].se);
}
}
return ans;
}
#ifdef FEXT
int a[100005];
signed main(){
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
freopen("KEK.inp", "r", stdin);
freopen("KEK.out", "w", stdout);
int n, start, d; cin >> n >> start >> d;
For(i, 0, n){
cin >> a[i];
}
ll ans = findMaxAttraction(n, start, d, a);
cout << ans << endl;
}
#endif
/*
==================================================+
INPUT: |
--------------------------------------------------|
--------------------------------------------------|
==================================================+
OUTPUT: |
--------------------------------------------------|
--------------------------------------------------|
==================================================+
*/
# | 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... |