# | 제출 시각 | 아이디 | 문제 | 언어 | 결과 | 실행 시간 | 메모리 |
---|---|---|---|---|---|---|---|
956994 | Vladth11 | 추월 (IOI23_overtaking) | C++17 | 0 ms | 0 KiB |
이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
#include "overtaking.h"
#define int ll
using namespace std;
typedef long long ll;
typedef pair <ll, ll> pii;
const ll NMAX = 20000001;
const ll INF = 1e18;
const ll nrbits = 20;
const ll MOD = 998244353;
const pii NEUTRU = {0, 0};
struct Node {
/// max(x + a, b)
int st, dr;
ll maxi; /// basically asta e valoarea lui f(dr)
pii lazy;
ll eval(ll x) {
return max(x + lazy.first, lazy.second);
}
};
Node aint[NMAX];
int cnt;
pii combine(pii nou, pii a) {
return {a.first + nou.first, max(a.second + nou.first, nou.second)};
}
void propaga(int node, ll st, ll dr) {
if(node == -1) return;
if(st != dr) {
if(aint[node].st == -1) {
aint[node].st = cnt;
aint[cnt++] = ({-1, -1, (st + dr) / 2, NEUTRU});
}
if(aint[node].dr == -1) {
aint[node].dr = cnt;
aint[cnt++] = ({-1, -1, dr, NEUTRU});
}
aint[aint[node].st].lazy = combine(aint[node].lazy, aint[aint[node].st].lazy);
aint[aint[node].dr].lazy = combine(aint[node].lazy, aint[aint[node].dr].lazy);
}
aint[node].maxi = aint[node].eval(aint[node].maxi);
aint[node].lazy = NEUTRU;
}
void update(int node, ll st, ll dr, ll a, ll b, pii functie) {
propaga(node, st, dr);
if(a <= st && dr <= b) {
aint[node].lazy = combine(functie, aint[node].lazy);
return;
}
ll mid = (st + dr) / 2;
if(a <= mid) {
if(aint[node].st == -1) {
aint[node].st = cnt;
aint[cnt++] = ({-1, -1, mid, NEUTRU});
}
update(aint[node].st, st, mid, a, b, functie);
}
if(b > mid) {
if(aint[node].dr == -1) {
aint[node].dr = cnt;
aint[cnt++] = ({-1, -1, dr, NEUTRU});
}
update(aint[node].dr, mid + 1, dr, a, b, functie);
}
propaga(aint[node].st, st, mid);
propaga(aint[node].dr, mid + 1, dr);
if(aint[node].dr != -1)
aint[node].maxi = aint[aint[node].dr].maxi;
else
aint[node].maxi = dr;
/// Calculez valoarea lui f(dr)
}
ll cb(int node, ll st, ll dr, ll val) {
propaga(node, st, dr);
if(st == dr) {
return st;
}
ll mid = (st + dr) / 2;
ll maxist = mid;
if(aint[node].st != -1) {
propaga(aint[node].st, st, mid);
maxist = aint[aint[node].st].maxi;
}
// debugs(st);
// debugs(dr);
// debug(maxist);
if(maxist > val) { /// vrem pe alea care au ajuns strict inaintea mea (ca autobuz cartof) - la cazul de egalitate...ori tu (ca de ala de rezerva) esti mai rapid deci e bine ca nu de updatez...ori esti mai incet...deci nici macar nu te voi afecta daca te updatez
/// mergea si asa, dar pt convenineta am scos pana la urma pe alea mai rapide ca autobuzele de rezerva fiindca nu ne interseaza deloc
if(aint[node].st == -1) {
aint[node].st = cnt;
aint[cnt++] = ({-1, -1, mid, NEUTRU});
}
return cb(aint[node].st, st, mid, val);
}
if(aint[node].dr == -1) {
aint[node].dr = cnt;
aint[cnt++] = ({-1, -1, dr, NEUTRU});
}
return cb(aint[node].dr, mid + 1, dr, val);
}
ll query(int node, ll st, ll dr, ll nr) {
propaga(node, st, dr);
if(st == dr) {
return aint[node].maxi;
}
ll mid = (st + dr) / 2;
if(nr <= mid) {
return query(aint[node].st, st, mid, nr);
}
return query(aint[node].dr, mid + 1, dr, nr);
}
ll panaAcum[NMAX];
void init(signed L, signed N, std::vector<long long> T, std::vector<signed> W, signed X, signed M, std::vector<signed> S) {
vector <int> indici;
aint[cnt++] = ({-1, -1, INF, NEUTRU});
for(int i = 0; i < N; i++) {
indici[cnt++] = (i);
panaAcum[i] = T[i];
}
sort(indici.begin(), indici.end(), [&W](const int &a, const int &b) {
return W[a] > W[b];
});
while(indici.size() && W[indici.back()] <= X) {
indici.pop_back();
}
for(int i = 1; i < M; i++) { /// de la 1
//debug(i);
sort(indici.begin(), indici.end(), [&W, &panaAcum](const int &a, const int &b) {
return ((pii){panaAcum[a], W[a]} < (pii){panaAcum[b], W[b]});
});
ll maxim = 0;
vector <ll> unde; /// pt fiecare indice calculam pe cine afecteaza
for(int j = 0; j < indici.size(); j++) {
unde[cnt++] = (cb(0, 0, INF, panaAcum[indici[j]]));
}
update(0, 0, INF, 0, INF, {1LL * X * (S[i] - S[i - 1]), 0});
for(int j = 0; j < indici.size(); j++) {
panaAcum[indici[j]] += 1LL * W[indici[j]] * (S[i] - S[i - 1]);
maxim = max(maxim, panaAcum[indici[j]]);
panaAcum[indici[j]] = maxim;
// debugs(indici[j]);
// debug(panaAcum[indici[j]]);
// debug(unde[j]);
update(0, 0, INF, unde[j], INF, {0, maxim});
}
}
}
long long arrival_time(long long Y) {
return query(0, 0, INF, Y);
}