제출 #845851

#제출 시각아이디문제언어결과실행 시간메모리
845851mircea_007추월 (IOI23_overtaking)C++17
100 / 100
1780 ms471536 KiB
#include "overtaking.h" #pragma GCC optimize( "O3,Ofast,unroll-loops" ) // de ce nu #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <vector> #include <map> using ll = long long; #define magic_sauce inline __attribute__((always_inline)) magic_sauce ll max( ll a, ll b ){ return a > b ? a : b; } const int MAXN = 1000; const int MAXM = 1000; const ll INF = 1e18; const ll NIL = -1; struct Range { ll begin; ll val; magic_sauce Range( ll a, ll b ) : begin( a ), val( b ) {} }; struct Function { std::vector<Range> ranges; ll add; magic_sauce ll operator ()( ll x ){ int st = 0, dr = (int)ranges.size(), mij; while( dr - st > 1 ){ if( ranges[mij = (st + dr) >> 1].begin > x ) dr = mij; else st = mij; } if( ranges[st].val >= 0 ) return ranges[st].val; return x + add; } // compunerea de functii void operator *= ( Function &other ){ std::vector<Range> new_ranges; int i, j, k, n = (int)ranges.size(), m = (int)other.ranges.size();; int st, dr, mij; ll start, end; for( i = 0 ; i < n ; i++ ){ start = ranges[i].begin; if( i + 1 < n ) end = ranges[i + 1].begin; else end = INF; if( ranges[i].val >= 0 ) new_ranges.emplace_back( start, other( ranges[i].val ) ); else{ // functie liniara // [start, end) -> [start + add, end + add) // adaugam tot ce este in range-ul [it_start, it_end) doar ca + add // tratam separat intervalul ce contine pe start st = 0; dr = m; while( dr - st > 1 ) if( other.ranges[mij = (st + dr) >> 1].begin > start + add ) dr = mij; else st = mij; j = st; // cazul separat new_ranges.emplace_back( start, other.ranges[j].val ); st = -1; dr = m; while( dr - st > 1 ){ if( other.ranges[mij = (st + dr) >> 1].begin < end + add ) st = mij; else dr = mij; } j++; k = dr; while( j < k ){ new_ranges.emplace_back( other.ranges[j].begin - add, other.ranges[j].val ); j++; } } } // prune next ranges ranges = new_ranges; add += other.add; } }; struct Solver { int l, n, x, m; std::vector<ll> t0; // timpul de pornire al autobuzelor std::vector<int> speed; // s/m std::vector<int> stat; // sorting station ll dp[MAXM][MAXN]; std::map<ll, ll> slowest[MAXM]; Function f[MAXM]; void calc_dp(){ int i, j; // facem ce spune enuntul for( i = 0 ; i < n ; i++ ) dp[0][i] = t0[i]; for( i = 1 ; i < m ; i++ ){ // for( j = 0 ; j < n ; j++ ) // e[j] = dp[i - 1][j] + ((ll)speed[j]) * (stat[i] - stat[i - 1]); for( j = 0 ; j < n ; j++ ) slowest[i][dp[i - 1][j]] = max( slowest[i][dp[i - 1][j]], dp[i - 1][j] + ((ll)speed[j]) * (stat[i] - stat[i - 1]) ); ll prev = -1; for( auto p : slowest[i] ){ prev = max( slowest[i][p.first], prev ); slowest[i][p.first] = prev; } for( j = 0 ; j < n ; j++ ){ dp[i][j] = dp[i - 1][j] + ((ll)speed[j]) * (stat[i] - stat[i - 1]); auto it = slowest[i].lower_bound( dp[i - 1][j] ); if( it != slowest[i].begin() ){ it--; dp[i][j] = max( dp[i][j], it->second ); } } } } void calc_map( int i ){ ll add = ((ll)x) * (stat[i] - stat[i - 1]); f[i].add = add; // daca am ajuns primii suntem liberi sa facem ce vrem f[i].ranges.emplace_back( 0, NIL ); auto it = slowest[i].begin(); auto next = it; while( it != slowest[i].end() ){ next++; ll start = it->first; ll cand = it->second; ll end = INF; if( next != slowest[i].end() ) end = next->first; start++; end++; // [start, cand - add) -> t' = cand // [cand - add, end) -> t' = t + add ll mij = cand - add; if( start < mij ) f[i].ranges.emplace_back( start, cand ); else mij = start; if( mij < end ) f[i].ranges.emplace_back( mij, NIL ); it = next; } } void compress_maps(){ for( int p2 = 1 ; p2 < 1024 ; p2 <<= 1 ) for( int i = 1 ; i + p2 < m ; i += (p2 << 1) ) f[i] *= f[i + p2]; } void pre(){ // using the dp from the statement we precalculate the positions of the other bussesx calc_dp(); // the old query function is a repeated aplication of M functions (in the math sense) // therefore we can hold these functions as a reunion of several intervals // each being either a constant function or a linear function with slope 1 for( int i = 1 ; i < m ; i++ ) calc_map( i ); compress_maps(); } ll query( ll t ){ return f[1]( t ); } } sol; void init( int L, int N, std::vector<ll> T, std::vector<int> W, int X, int M, std::vector<int> S ){ // first of all, anything faster than x doesn't matter // therefore we can assume that the special bus in the // fastest one and the others are slowing it down // each buss has to worry only about the ones slower than itsself // for this exact reason, all the busse's paths (exept N) are predetermined // some precalculation sol.l = L; sol.n = N; sol.x = X; sol.m = M; sol.t0 = T; sol.speed = W; sol.stat = S; sol.pre(); } ll arrival_time( ll Y ){ return sol.query( Y ); return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...