제출 #788525

#제출 시각아이디문제언어결과실행 시간메모리
788525fatemetmhrShortcut (IOI16_shortcut)C++17
93 / 100
2065 ms162580 KiB
//  ~ Be Name Khoda ~  //
 
#include "shortcut.h"
//#pragma GCC optimize ("O3")
//#pragma GCC target("avx2")
#pragma GCC optimize("unroll-loops,Ofast")
#include <bits/stdc++.h>
 
using namespace std;
 
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
 
 
typedef long long ll;
 
#define pb       push_back
#define mp       make_pair
#define all(x)   x.begin(), x.end()
#define fi       first
#define se       second
 
const int maxn  =  1e6   + 10;
const int maxn5 =  3e5   + 10;
const int maxnl =  1e7   + 10;
const int maxn3 =  1e3   + 10;
const ll mod   =  1e9   + 7;
const int lg    =  20;
const ll  inf   =  1e18;
 
int n, root[maxn5], newnode = 2;
ll c;
vector <ll> d;
ll ps[maxn5];
vector <ll> av;
 
// c + d[i] + ps[i] - ps[a] + cons - ps[b] <= lim
// d[i] + ps[i] + cons <= lim - c + ps[b] + ps[a]

namespace seg{

    pair <ll, ll> mx[maxnl];
    int chil[maxnl][2];

    pair <ll, ll> comb(pair <ll, ll> a, pair <ll, ll> b){
        return {max(a.fi, b.fi), max(a.se, b.se)};
    }

    void cop(int a, int b){
        chil[a][0] = chil[b][0];
        chil[a][1] = chil[b][1];
        mx[a] = mx[b];
    }

    void upd(int l, int r, int ind, pair <ll, ll> val, int v){
        if(r - l == 1){
            mx[v] = val;
            return;
        }
        int mid = (l + r) >> 1;
        int v2 = newnode++;
        if(ind < mid){
            cop(v2, chil[v][0]);
            chil[v][0] = v2;
            upd(l, mid, ind, val, v2);
        }
        else{
            cop(v2, chil[v][1]);
            chil[v][1] = v2;
            upd(mid, r, ind, val, v2);
        }
        mx[v] = comb(mx[chil[v][0]], mx[chil[v][1]]);
    }

    pair <ll, ll> get_max(int l, int r, int lq, int rq, int v){
        if(rq <= l || r <= lq || v == 0)
            return {-inf, -inf};
        if(lq <= l && r <= rq)
            return mx[v];
        int mid = (l + r) >> 1;
        return comb(get_max(l, mid, lq, rq, chil[v][0]), get_max(mid, r, lq, rq, chil[v][1]));
    }
}

struct RMQ{

    ll mx[maxn5];
    bool ty;

    void build(int n){
        if(ty)
            for(int i = 1; i < n; i++)
                mx[i] = max(mx[i], mx[i - 1]);
        else
            for(int i = n - 2; i >= 0; i--)
                mx[i] = max(mx[i], mx[i + 1]);
    }


} rmq[2][2];


bool check2(int a, int b, int ty, ll lim){
    //cout << "for " << a << ' ' << b << ' ' << ty << ' ' << lim << endl;
    //cout << rmq[0][ty].get_max(a, n - 1) << ' ' << lim - c + (ty ? -1 : 1) * ps[b] - ps[a] << endl;
    if(rmq[0][ty].mx[a] > lim - c + (ty ? -1 : 1) * ps[b] + ps[a])
        return false;
    if(rmq[1][ty].mx[a] > lim - c + (ty ? -1 : 1) * ps[b] - ps[a])
        return false;
    //cout << "result in true " << endl;
    return true;
}
 
bool check(ll lim){
    //cout << "************** in lim " << lim << endl;
    for(int i = 0; i < n; i++){
        if(i == n - 1){
            for(int x = 0; x < 2; x++) for(int y = 0; y < 2; y++)
                rmq[x][y].mx[i] = -inf;
            continue;
        }
        int pt = upper_bound(all(av), lim - (d[i] - ps[i])) - av.begin();
        auto ans = seg::get_max(0, n, pt, n, root[i + 1]);
        //cout << "in " << i << ' ' << pt << ' ' << av.size() << endl;
        ll cons[2] = {ans.fi, ans.se};
        //cout << i << ' ' << cons[0] << ' ' << cons[1] << endl;
        for(int x = 0; x < 2; x++) for(int y = 0; y < 2; y++)
            rmq[x][y].mx[i] = d[i] + cons[y] + ps[i] * (x ? -1 : 1);
    }
    rmq[0][0].ty = 0;
    rmq[0][1].ty = 0;
    rmq[1][0].ty = 1;
    rmq[1][1].ty = 1;
    rmq[0][0].build(n); // 0 is suf
    rmq[0][1].build(n);
    rmq[1][0].build(n);
    rmq[1][1].build(n);

    for(int i = 0; i < n; i++){
        int lo = i, hi = n;
        while(hi - lo > 1){
            int mid = (lo + hi) >> 1;
            if(check2(i, mid, 0, lim))
                hi = mid;
            else
                lo = mid;
        }
        int l = max(i + 1, hi);
 
        lo = i; hi = n;
        while(hi - lo > 1){
            int mid = (lo + hi) >> 1;
            if(check2(i, mid, 1, lim))
                lo = mid;
            else
                hi = mid;
        }
        int r = min(n, lo);
        //cout << "ok " << i << ' ' << l << ' ' << r << endl;
        if(l <= r)
            return true;
    }
    return false;

    /*

    for(int i = 0; i < n; i++) if(pt[i] < av[i].size()){
        int b = 0;
        for(auto [w, a] : srt[i]){
            while(b + 1 < n && c + d[i] + w + av[i][pt[i]].se.fi - ps[b] > lim)
                b++;
            l[a] = max(l[a], b);
        }
        b = n - 1;
        for(auto [w, a] : srt[i]){
            while(b && c + d[i] + w + av[i][pt[i]].se.se + ps[b] > lim)
                b--;
            r[a] = min(r[a], b);
        }



        /*
        int lo = i, hi = n;
        while(hi - lo > 1){
            int mid = (lo + hi) >> 1;
            if(check(i, mid, 0, lim))
                hi = mid;
            else
                lo = mid;
        }
        l = max(i + 1, hi);
 
        lo = i; hi = n;
        while(hi - lo > 1){
            int mid = (lo + hi) >> 1;
            if(check(i, mid, 1, lim))
                lo = mid;
            else
                hi = mid;
        }
        r = min(n, lo);
        //////cout << "ok " << lim << ' ' << i << ' ' << l << ' ' << r << endl;
        if(l <= r)
            return true;
 
 
 
        /*
        bool re = true;
        for(int j = 0; j < n && re; j++) for(int k = j + 1; k < n && re; k++) if(dis(j, k) + d[j] + d[k] > lim){
            ll dis1 = dis(i, j);
            ll need = lim - c - d[j] - d[k] - dis1;
            if(need < 0)
                re = false;
            int ptl = k - (upper_bound(all(av[k][0]), need) - av[k][0].begin() - 1);
            int ptr = k + (upper_bound(all(av[k][1]), need) - av[k][1].begin() - 1);
            l = max(l, ptl);
            r = min(r, ptr);
            //////cout << lim << ' ' << i << ' ' << j << ' ' << k << ' ' << l << ' ' << r << endl;
            if(l > r)
                re = false;
        }
        if(re)
            return true;
    }
    */
}
 
long long find_shortcut(int N, std::vector<int> l, std::vector<int> D, int C)
{
    n = N;
    c = C;
    for(auto u : D)
        d.pb(u);
    ps[0] = 0;
    for(int i = 0; i < n; i++){
        if(i)
            ps[i] = ps[i - 1] + l[i - 1];
        av.pb(d[i] + ps[i]);
    }
    sort(all(av));
    av.resize(unique(all(av)) - av.begin());
    int last = 1;
    seg::mx[0] = {-inf, -inf};
    for(int i = n - 1; i >= 0; i--){
        root[i] = newnode++;
        seg::cop(root[i], last);
        int pt = lower_bound(all(av), d[i] + ps[i]) - av.begin();
        seg::upd(0, n, pt, mp(d[i] + ps[i], d[i] - ps[i]), root[i]);
        last = root[i];
    }
    /*
    for(int i = 0; i < n; i++){
        for(int j = i + 1; j < n; j++)
            av[i].pb({dis(i, j) + d[i] + d[j], {d[j] + ps[j], d[j] - ps[j]}});
        //if(i == 1)
        //    ////cout << av[i][1].back().se << ' ' << av[i][1].back().fi << endl;
        sort(all(av[i]));
        for(int j = int(av[i].size()) - 2; j >= 0; j--){
            //if(i == 1)
            //    ////cout << j << endl;
            av[i][j].se.fi = max(av[i][j].se.fi, av[i][j + 1].se.fi);
            av[i][j].se.se = max(av[i][j].se.se, av[i][j + 1].se.se);
        }
        //if(i == 1)
        //    ////cout << av[i][1].back().se << ' ' << av[i][1].back().fi << endl;
    }
    */
    ll lo = -1, hi = mod * (n + 3);
    while(hi - lo > 1){
        ll mid = (lo + hi) >> 1;
        if(check(mid))
            hi = mid;
        else
            lo = mid;
    }
    return hi;
}

컴파일 시 표준 에러 (stderr) 메시지

shortcut.cpp:182:9: warning: "/*" within comment [-Wcomment]
  182 |         /*
      |          
shortcut.cpp:208:9: warning: "/*" within comment [-Wcomment]
  208 |         /*
      |
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...