제출 #1338261

#제출 시각아이디문제언어결과실행 시간메모리
1338261SmuggingSpunSky Walking (IOI19_walk)C++20
100 / 100
1245 ms160180 KiB
#include "walk.h"
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool minimize(T& a, T b){
  if(a > b){
    a = b;
    return true;
  }
  return false;
}
vector<int>x, h, l, r, y;
int n, m, s, t;
namespace sub1{
  struct Data{
    int x, y;
    ll w;
    Data(){}
    Data(int _x, int _y, ll _w) : x(_x), y(_y), w(_w) {}
    friend bool operator <(const Data a, const Data b){
      return a.w > b.w;
    }
  };
  ll solve(){
    map<pair<int, int>, ll>d;
    priority_queue<Data>pq;
    pq.push(Data(x[s], 0, d[make_pair(x[s], 0)] = 0));
    while(!pq.empty()){
      auto [px, py, dw] = pq.top();
      pq.pop();
      if(dw == d[make_pair(px, py)]){
        int idx = lower_bound(x.begin(), x.end(), px) - x.begin();
        for(int i = 0; i < m; i++){
          if(l[i] <= idx && r[i] >= idx && h[idx] >= y[i]){
            ll dnw = dw + abs(py - y[i]);
            map<pair<int, int>, ll>::iterator it = d.find(make_pair(px, y[i]));
            if(it == d.end() || it->second > dnw){
              pq.push(Data(px, y[i], d[make_pair(px, y[i])] = dnw));
            }
            if(py == y[i]){
              for(int j = l[i]; j <= r[i]; j++){
                if(h[j] >= y[i]){
                  dnw = dw + abs(px - x[j]);
                  if((it = d.find(make_pair(x[j], py))) == d.end() || it->second > dnw){
                    pq.push(Data(x[j], py, d[make_pair(x[j], py)] = dnw));
                  }
                }
              }
            }
          } 
        }
        auto it = d.find(make_pair(px, 0));
        dw += py;
        if(it == d.end() || it->second > dw){
          pq.push(Data(px, 0, d[make_pair(px, 0)] = dw));
        }
      }
    }
    auto it = d.find(make_pair(x[t], 0));
    return it == d.end() ? -1 : it->second;
  }
}
const ll INF = 1e18;
const int lim = 1e5 + 5;
namespace sub34{
  const int LIM = 1e9 + 36;
  struct DynamicSegmentTree{
    struct Node{
      ll val;
      int lc, rc;
      Node(){
        lc = rc = -1;
        val = INF;
      }
    };
    vector<Node>st;
    DynamicSegmentTree(){
      st.push_back(Node());
    }
    void new_node(int id){
      if(st[id].lc == -1){
        st[id].lc = st.size();
        st.push_back(Node());
      }
      if(st[id].rc == -1){
        st[id].rc = st.size();
        st.push_back(Node());
      }
    }
    void update(int id, int l, int r, int p, ll x){
      if(l == r){
        st[id].val = x;
        return;
      }
      int m = (l + r) >> 1;
      new_node(id);
      if(m < p){
        update(st[id].rc, m + 1, r, p, x);
      }
      else{
        update(st[id].lc, l, m, p, x);
      }
      st[id].val = min(st[st[id].lc].val, st[st[id].rc].val);
    }
    ll get(int id, int l, int r, int u, int v){
      if(l > v || r < u || id == -1){
        return INF;
      }
      if(u <= l && v >= r){
        return st[id].val;
      }
      int m = (l + r) >> 1;
      return min(get(st[id].lc, l, m, u, v), get(st[id].rc, m + 1, r, u, v));
    }
  };
  DynamicSegmentTree st_plus, st_minus;
  ll solve(){
    vector<vector<int>>event(n + 1);
    map<int, vector<pair<int, int>>>range;
    for(int i = 0; i < m; i++){
      range[y[i]].push_back(make_pair(l[i], r[i]));
    }
    for(auto& [vy, ve] : range){
      sort(ve.begin(), ve.end());
      int L = ve[0].first, R = ve[0].second;
      for(int i = 1; i < ve.size(); i++){
        if(ve[i].first == R){
          R = ve[i].second;
        }
        else{
          event[L].push_back(vy);
          event[R + 1].push_back(-vy);
          tie(L, R) = ve[i];
        }
      }
      event[L].push_back(vy);
      event[R + 1].push_back(-vy);
    }
    for(int& vy : event[0]){
      st_plus.update(0, 0, LIM, vy, vy << 1);
      st_minus.update(0, 0, LIM, vy, 0);
    }
    for(int i = 1; i < n; i++){
      sort(event[i].begin(), event[i].end());
      for(int& vy : event[i]){
        if(vy < 0){
          st_plus.update(0, 0, LIM, -vy, INF);
          st_minus.update(0, 0, LIM, -vy, INF);
        }
        else{
          ll x = min(st_plus.get(0, 0, LIM, vy, LIM) - vy, st_minus.get(0, 0, LIM, 0, vy) + vy);
          st_plus.update(0, 0, LIM, vy, x + vy);
          st_minus.update(0, 0, LIM, vy, x - vy);
        }
      }
    }
    return st_plus.st[0].val == INF ? -1 : st_plus.st[0].val + x[n - 1] - x[0];
  }
}
namespace sub25{
  const int LIM = 18e5 + 36;
  vector<pair<int, int>>g[LIM];
  pair<int, int>lst[lim];
  int ptr_ph, N = 0;
  ll dis[LIM];
  void add_sky_walk(int L, int R, int Y){
    l.push_back(L);
    r.push_back(R);
    y.push_back(Y);
  }
  void add_edge(int u, int v, int w){
    g[u].push_back(make_pair(v, w));
    g[v].push_back(make_pair(u, w));
  }
  ll solve(){
    vector<pair<int, int>>ph(n);
    for(int i = 0; i < n; i++){
      ph[i] = make_pair(h[i], i);
    }
    sort(ph.begin(), ph.end(), greater<pair<int, int>>());
    for(int x : {s, t}){
      vector<pair<int, int>>py(m);
      for(int i = ptr_ph = 0; i < m; i++){
        py[i] = make_pair(y[i], i);
      }
      sort(py.begin(), py.end(), greater<pair<int, int>>());
      set<int>S;
      for(auto& [vy, i] : py){
        while(ptr_ph < n && ph[ptr_ph].first >= vy){
          S.insert(ph[ptr_ph++].second);
        }
        if(l[i] < x && r[i] > x){
          int left = *prev(S.upper_bound(x)), right = *S.lower_bound(x);
          if(r[i] > right){
            add_sky_walk(right, r[i], vy);
          }
          if(l[i] < left){
            add_sky_walk(l[i], left, vy);
          }
          if(left < right){
            add_sky_walk(left, right, vy);
          }
        }
      }
      m = l.size();
    }
    vector<pair<int, int>>py(m);
    for(int i = ptr_ph = 0; i < m; i++){
      py[i] = make_pair(y[i], i);
    }
    sort(py.begin(), py.end(), greater<pair<int, int>>());
    set<int>S;
    fill(lst, lst + n, make_pair(-1, -1));
    for(auto& [vy, i] : py){
      while(ptr_ph < n && ph[ptr_ph].first >= vy){
        S.insert(ph[ptr_ph++].second);
      }
      S.insert(l[i]);
      S.insert(r[i]);
      vector<int>trash;
      int pre_cix = -1;
      for(auto it = S.find(l[i]); it != S.end() && *it <= r[i]; it++){
        int cix = *it;
        if(lst[cix].first != -1){
          add_edge(N, lst[cix].first, lst[cix].second - vy);
        }
        if(pre_cix != -1){
          add_edge(N, N - 1, x[cix] - x[pre_cix]);
        }
        lst[pre_cix = cix] = make_pair(N++, vy);
        if(cix != l[i] && cix != r[i]){
          trash.push_back(cix);
        }
      }
      for(int& x : trash){
        S.erase(x);
      }
    }
    for(int x : {s, t}){
      if(lst[x].first == -1){
        return -1;
      }
      add_edge(lst[x].first, N++, lst[x].second);
    }
    memset(dis, 0x0f, sizeof(dis));
    priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>>pq;
    pq.push(make_pair(dis[N - 2] = 0, N - 2));
    while(!pq.empty()){
      auto [cw, cu] = pq.top();
      pq.pop();
      if(cw == dis[cu]){
        for(auto& [ev, ew] : g[cu]){
          if(minimize(dis[ev], cw + ew)){
            pq.push(make_pair(dis[ev], ev));
          }
        }
      }
    }
    return dis[N - 1] > INF ? -1 : dis[N - 1];
  }
}
ll min_distance(vector<int>_x, vector<int>_h, vector<int>_l, vector<int>_r, vector<int>_y, int _s, int _t){
  s = _s;
  t = _t;
  swap(x, _x);
  swap(h, _h);
  swap(l, _l);
  swap(r, _r);
  swap(y, _y);
  if(max(n = x.size(), m = l.size()) <= 50){
    return sub1::solve();
  }
  if(s == 0 && t == n - 1){
    return sub34::solve();
  }
  return sub25::solve();
}
#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...