# | 제출 시각 | 아이디 | 문제 | 언어 | 결과 | 실행 시간 | 메모리 |
---|---|---|---|---|---|---|---|
905435 | pemguimn | 휴가 (IOI14_holiday) | C++14 | 0 ms | 0 KiB |
이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
// #include "holiday.h"
#define int long long
#define pii pair<int, int>
using namespace std;
const int N = 3e5 + 5, INF = 2e9;
int n, d, start, a[N], ori[N], sz; long long ans = -INF;
vector<int> val;
struct node{
int cnt; long long sum;
node *l, *r;
node(){
l = r = nullptr, cnt = sum = 0;
}
};
node *root[N];
node *build(int l, int r){
node *p = new node();
if(l == r){
return p;
}
int mid = (l + r) / 2;
p -> l = build(l, mid);
p -> r = build(mid + 1, r);
return p;
}
node* upd(node *k, int tl, int tr, int i, int x){
node *p = new node();
if(tl == tr){
p -> cnt = k -> cnt + 1;
p -> sum = k -> sum + ori[tl];
return p;
}
int mid = (tl + tr) / 2;
if(i <= mid){
p -> l = upd(k -> l, tl, mid, i, x);
p -> r = k -> r;
} else{
p -> l = k -> l;
p -> r = upd(k -> r, mid + 1, tr, i, x);
}
p -> cnt = p -> l -> cnt + p -> r -> cnt;
p -> sum = p -> l -> sum + p -> r -> sum;
return p;
}
long long query(node *l, node *r, int tl, int tr, int k){
if(tl == tr){
return 1LL * ori[tl] * min(k, r -> cnt - l -> cnt);
}
int mid = (tl + tr) / 2;
if(r -> r -> cnt - l -> r -> cnt >= k){
return query(l -> r, r -> r, mid + 1, tr, k);
} else{
// cout << ori[mid + 1] << " " << r -> r -> cnt - l -> r -> cnt << " " << r -> r -> sum - l -> r -> sum << endl;
return r -> r -> sum - l -> r -> sum + query(l -> l, r -> l, tl, mid, k - (r -> r -> cnt - l -> r -> cnt));
}
}
long long cost(int l, int start, int r){
int queryop = min(d - (r - l + min(r - start, start - l)), r - l + 1);
if(queryop < 0) return -INF;
// cout << l << ' ' << start << " " << r << ' ' << queryop << " " << query(root[l - 1], root[r], 0, sz, queryop)<< endl;
return query(root[l - 1], root[r], 0, sz, queryop);
}
void dnc(int l, int r, int optl, int optr){
if(l > r) return;
int mid = (l + r) / 2;
pair<long long, int> best = {-INF, 0};
for(int i = optl; i <= min(optr, mid); i++){
best = max(best, {cost(i, start, mid), i});
}
ans = max(ans, best.first);
dnc(l, mid - 1, optl, best.second);
dnc(mid + 1, r, best.second, optr);
}
int findMaxAttraction(int nn, int startt, int dd, int attraction[]){
n = nn, start = startt, d = dd;
start++;
for(int i = 0; i < n; i++){
a[i + 1] = attraction[i];
}
for(int i = 1; i <= n; i++) val.push_back(a[i]);
sort(val.begin(), val.end()); val.resize(unique(val.begin(), val.end()) - val.begin());
for(int i = 0; i < (int) val.size(); i++) ori[i] = val[i];
sz = val.size() - 1;
root[0] = build(0, sz);
for(int i = 1; i <= n; i++){
a[i] = lower_bound(val.begin(), val.end(), a[i]) - val.begin();
root[i] = upd(root[i - 1], 0, sz, a[i], 1);
}
dnc(start, n, 1, start);
return ans;
}