Submission #1225943

#TimeUsernameProblemLanguageResultExecution timeMemory
1225943Hamed_GhaffariSky Walking (IOI19_walk)C++20
25 / 100
493 ms141344 KiB
#include "walk.h"
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

#define X first
#define Y second
#define lc id<<1
#define rc lc|1
#define mid ((l+r)>>1)

const int MXN = 1e5+5;
const ll inf = 1e18;

namespace sub4 {
    int n, m, ord[MXN], pos[MXN];
    ll dis[MXN];
    vector<int> y, op[MXN], cl[MXN];
    ll seg[MXN<<2][2];
    void build(int l=0, int r=m, int id=1) {
        seg[id][0] = seg[id][1] = inf*2;
        if(r-l == 1) return;
        build(l, mid, lc);
        build(mid, r, rc);
    }
    void upd(int p, bool x, int l=0, int r=m, int id=1) {
        if(r-l == 1) {
            if(x) seg[id][0] = dis[ord[l]]+y[ord[l]], seg[id][1] = dis[ord[l]]-y[ord[l]];
            else seg[id][0] = seg[id][1] = inf*2;
            return;
        }
        p<mid ? upd(p, x, l, mid, lc) : upd(p, x, mid, r, rc);
        seg[id][0] = min(seg[lc][0], seg[rc][0]);
        seg[id][1] = min(seg[lc][1], seg[rc][1]);
    }
    ll get(int s, int e, bool x, int l=0, int r=m, int id=1) {
        if(s>=r || l>=e) return inf*2;
        if(s<=l && r<=e) return seg[id][x];
        return min(get(s, e, x, l, mid, lc), get(s, e, x, mid, r, rc));
    }
    ll min_distance(vector<int> x, vector<int> h, vector<int> l, vector<int> r, vector<int> y, int s, int g) {
        n = x.size(); m = y.size();
        sub4::y = y;
        iota(ord, ord+m, 0);
        sort(ord, ord+m, [&](int i, int j) {
            return y[i]<y[j];
        });
        for(int i=0; i<m; i++)
            pos[ord[i]] = i;
        build();
        for(int i=0; i<m; i++) {
            op[l[i]].push_back(i);
            if(r[i]+1<n) cl[r[i]+1].push_back(i);
        }
        for(int i : op[0]) {
            dis[i] = y[i];
            upd(pos[i], 1);
        }
        for(int i=1; i<n; i++) {
            for(int j : cl[i]) upd(pos[j], 0);
            for(int j : op[i]) {
                int lb=-1, rb=m, mb;
                while(rb-lb>1) {
                    mb = (lb+rb)>>1;
                    (y[ord[mb]]>h[i] ? rb : lb) = mb;
                }
                dis[j] = min(get(pos[j], rb, 0)-y[j], get(0, pos[j]+1, 1)+y[j]);
                upd(pos[j], 1);
            }
        }
        int lb=-1, rb=m, mb;
        while(rb-lb>1) {
            mb = (lb+rb)>>1;
            (y[ord[mb]]>h[n-1] ? rb : lb) = mb;
        }
        ll ans = get(0, rb, 0);
        if(ans>=inf) return -1;
        return ans + x[n-1] - x[0];
    }
}

int ordn[MXN], ordm[MXN], N;
vector<pii> vec[MXN];
vector<pii> G[MXN*23];
ll dis[MXN*23];

inline void add(int u, int v, int w) {
    G[u].push_back({v, w});
    G[v].push_back({u, w});
}

ll min_distance(vector<int> x, vector<int> h, vector<int> l, vector<int> r, vector<int> y, int s, int g) {
    if(s==0 && g==x.size()-1) return sub4::min_distance(x, h, l, r, y, s, g);
    int n = x.size(), m = y.size();
    iota(ordn, ordn+n, 0);
    sort(ordn, ordn+n, [&](int i, int j) {
        return h[i]>h[j];
    });
    iota(ordm, ordm+m, 0);
    sort(ordm, ordm+m, [&](int i, int j) {
        return y[i]>y[j];
    });
    int ptr=0;
    set<int> st;
    for(int i=0; i<m; i++) {
        while(ptr<n && h[ordn[ptr]]>=y[ordm[i]])
            st.insert(ordn[ptr++]);
        int lst = -1, id = -1;
        for(auto it = st.lower_bound(l[ordm[i]]); it!=st.end() && (*it)<=r[ordm[i]]; it++) {
            if(lst != -1) add(id, N, x[*it]-x[lst]);
            lst = *it;
            id = N;
            vec[*it].push_back({N++, y[ordm[i]]});
        }
    }
    vec[s].push_back({N++, 0});
    vec[g].push_back({N++, 0});
    for(int i=0; i<n; i++)
        for(int j=1; j<vec[i].size(); j++)
            add(vec[i][j-1].X, vec[i][j].X, vec[i][j-1].Y-vec[i][j].Y);
    fill(dis, dis+N, inf);        
    priority_queue<pll> pq;
    pq.push({dis[N-2]=0, N-2});
    while(!pq.empty()) {
        ll d = -pq.top().X;
        int v = pq.top().Y;
        pq.pop();
        if(d!=dis[v]) continue;
        for(auto [u, w] : G[v])
            if(dis[u]>d+w)
                pq.push({-(dis[u]=d+w), u});
    }
    return dis[N-1] >= inf ? -1 : dis[N-1];
}
#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...