제출 #1330878

#제출 시각아이디문제언어결과실행 시간메모리
1330878SmuggingSpun은하철도 (APIO24_train)C++20
100 / 100
902 ms22708 KiB
#include "train.h"
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll LINF = 1e18 + 36;
const int INF = 1e9 + 36;
template<class T>bool minimize(T& a, T b){
  if(a > b){
    a = b;
    return true;
  }
  return false;
}
int n, m, w;
vector<int>t, x, y, a, b, c, l, r;
namespace sub1{
  const int lim = 1e3 + 5;
  ll d[lim][lim];
  struct Data{
    int u, t;
    ll w;
    Data(){}
    Data(int _u, int _t, ll _w) : u(_u), t(_t), w(_w) {}
    friend bool operator <(Data a, Data b){
      return a.w > b.w;
    }
  };
  vector<int>g[lim];
  ll solve(){
    for(int i = 0; i < m; i++){
      g[x[i]].push_back(i);
    }
    priority_queue<Data>pq;
    memset(d, 0x0f, sizeof(d));
    pq.push(Data(0, 0, d[0][0] = 0));
    while(!pq.empty()){
      auto [u, time, dist] = pq.top();
      pq.pop();
      if(d[u][time] == dist){
        for(int& i : g[u]){
          if(a[i] >= time){
            ll new_dist = dist + c[i];
            for(int j = 0; j < w; j++){
              if(time < l[j] && a[i] > r[j]){
                new_dist += t[u];
              }
            }
            if(minimize(d[y[i]][b[i]], new_dist)){
              pq.push(Data(y[i], b[i], new_dist));
            }
          }
        }
      }
    }
    ll ans = LINF;
    for(int time = 0; time < lim; time++){
      ll cur = d[n - 1][time];
      for(int i = 0; i < w; i++){
        if(l[i] > time){
          cur += t[n - 1];
        }
      }
      minimize(ans, cur);
    }
    return ans == LINF ? -1 : ans;
  }
}
namespace sub2{
  struct Data{
    bool f;
    int t, i;
    Data(){}
    Data(bool _f, int _t, int _i) : f(_f), t(_t), i(_i) {}
    friend bool operator <(Data a, Data b){
      return a.t != b.t ? a.t < b.t : a.f < b.f;
    }
  };
  ll solve(){
    vector<Data>event;
    for(int i = 0; i < m; i++){
      event.push_back(Data(false, a[i], i));
      event.push_back(Data(true, b[i], i));
    }
    sort(event.begin(), event.end());
    vector<ll>ans(n, LINF), wait(n, LINF);
    ans[0] = 0;
    for(auto& [f, t, i] : event){
      if(!f){
        minimize(wait[y[i]], ans[x[i]] + c[i]);
      }
      else{
        minimize(ans[y[i]], wait[y[i]]);
      }
    }
    return ans[n - 1] == LINF ? -1 : ans[n - 1];
  }
}
namespace sub34{
  const int SIZE = 736;
  const int lim = 1e5 + 36;
  struct Train{
    int l, r, u, v, cost, low_meal;
    Train(){}
    Train(int _l, int _r, int _u, int _v, int _cost) : l(_l), r(_r), u(_u), v(_v), cost(_cost), low_meal(-1) {} 
  };
  struct Event{
    bool type;
    int time, id;
    Event(){}
    Event(bool _type, int _time, int _id) : type(_type), time(_time), id(_id) {}
    friend bool operator <(Event& a, Event& b){
      return a.time != b.time ? a.time < b.time : a.type < b.type;
    }
  };
  struct SegmentTree{
    vector<ll>st, lazy;
    int n;
    SegmentTree(){}
    SegmentTree(int n){
      st.assign((this->n = n) << 2 | 3, LINF);
      lazy.assign(n << 2 | 3, 0);
    }
    void propagate(int id, ll x){
      st[id] += x;
      lazy[id] += x;
    }
    void push_down(int id){
      propagate(id << 1, lazy[id]);
      propagate(id << 1 | 1, lazy[id]);
      lazy[id] = 0;
    }
    void update_range(int id, int l, int r, int u, int v, int x){
      if(l > v || r < u){
        return;
      }
      if(u <= l && v >= r){
        propagate(id, x);
        return;
      }
      int m = (l + r) >> 1;
      push_down(id);
      update_range(id << 1, l, m, u, v, x);
      update_range(id << 1 | 1, m + 1, r, u, v, x);
      st[id] = min(st[id << 1], st[id << 1 | 1]);
    }
    void update_range(int u, int v, int x){
      update_range(1, 1, n, u, v, x);
    }
    void update_pos(int p, ll x){
      int id = 1, l = 1, r = n;
      while(l < r){
        int m = (l + r) >> 1;
        push_down(id);
        id <<= 1;
        if(m < p){
          id |= 1;
          l = m + 1;
        }
        else{
          r = m;
        }
      }
      st[id] = x;
      while((id >>= 1) > 0){
        st[id] = min(st[id << 1], st[id << 1 | 1]);
      }
    }
    ll get_min_pref(int p){
      if(p == n){
        return st[1];
      }
      ll ans = LINF;
      int id = 1, l = 1, r = n;
      while(l < r){
        int m = (l + r) >> 1;
        push_down(id);
        id <<= 1;
        if(m <= p){
          minimize(ans, st[id]);
          id |= 1;
          l = m + 1;
        }
        else{
          r = m;
        }
      }
      return ans;
    }
  };
  struct FenwickTree{
    int bit[lim];
    FenwickTree(){
      memset(bit, 0, sizeof(bit));
    }
    void update(int p){
      for(p++; p < lim; p += p & -p){
        bit[p]++;
      }
    }
    int get(int p){
      int ans = 0;
      for(p++; p > 0; p -= p & -p){
        ans += bit[p];
      }
      return ans;
    }
  };
  FenwickTree fen_meal;
  ll dp[lim];
  ll solve(){
    vector<Train>train(1, Train(-1, 0, 0, 0, 0));
    for(int i = 0; i < m; i++){
      train.push_back(Train(a[i], b[i], x[i], y[i], c[i]));
    }
    sort(train.begin(), train.end(), [&] (auto i, auto j){
      return i.v != j.v ? i.v < j.v : i.r < j.r;
    });
    train.push_back(Train(INF, INF, n - 1, n - 1, 0));
    m += 2;
    vector<pair<int, int>>planet(n, make_pair(m, m - 1));
    vector<Event>event;
    for(int i = 0; i < m; i++){
      if(i == 0 || train[i].v != train[i - 1].v){
        planet[train[i].v].first = i;
      }
      if(i == m - 1 || train[i].v != train[i + 1].v){
        planet[train[i].v].second = i;
      }
      event.push_back(Event(false, train[i].l, i));
    }
    vector<SegmentTree>st;
    vector<int>heavy_planet;
    for(int i = 0; i < n; i++){
      int N = planet[i].second - planet[i].first + 1;
      if(N > SIZE){
        st.push_back(SegmentTree(N));
        heavy_planet.push_back(i);
      }
    }
    vector<pair<int, int>>meal(w);
    for(int i = 0; i < w; i++){
      meal[i] = make_pair(l[i], r[i]);
    }
    sort(meal.begin(), meal.end(), [&] (auto i, auto j){
      return i.first > j.first;
    });
    for(int i = 0; i < w; i++){
      event.push_back(Event(true, meal[i].second, i));
    }
    for(int i = 0; i < m; i++){
      int low = 0, high = w - 1;
      while(low <= high){
        int mid = (low + high) >> 1;
        if(meal[mid].first > train[i].r){
          low = (train[i].low_meal = mid) + 1;
        }
        else{
          high = mid - 1;
        }
      }
    }
    sort(event.begin(), event.end());
    memset(dp, 0x0f, sizeof(dp));
    dp[0] = 0;
    if(!heavy_planet.empty() && heavy_planet[0] == 0){
      st[0].update_pos(1, 0);
    }
    for(auto& [type, time, id] : event){
      if(type){
        fen_meal.update(id);
        for(int i = 0; i < heavy_planet.size(); i++){
          int vertex = heavy_planet[i], low = planet[vertex].first, high = planet[vertex].second, p = low - 1;
          while(low <= high){
            int mid = (low + high) >> 1;
            if(train[mid].r < meal[id].first){
              low = (p = mid) + 1;
            }
            else{
              high = mid - 1;
            }
          }
          st[i].update_range(1, p + 1 - planet[vertex].first, t[vertex]);
        }
      }
      else if(id > 0){
        int p = lower_bound(heavy_planet.begin(), heavy_planet.end(), train[id].u) - heavy_planet.begin();
        if(p < heavy_planet.size() && heavy_planet[p] == train[id].u){
          int low = planet[train[id].u].first, high = planet[train[id].u].second, pos = low - 1;
          while(low <= high){
            int mid = (low + high) >> 1;
            if(train[mid].r <= train[id].l){
              low = (pos = mid) + 1;
            }
            else{
              high = mid - 1;
            }
          }
          dp[id] = st[p].get_min_pref(pos - planet[train[id].u].first + 1) + train[id].cost;
        }
        else{
          for(int s = train[id].u, i = planet[s].first; i <= planet[s].second; i++){
            if(train[i].r > train[id].l){
              break;
            }
            minimize(dp[id], dp[i] + ll(t[s]) * fen_meal.get(train[i].low_meal) + train[id].cost);
          }
        }
        if((p = lower_bound(heavy_planet.begin(), heavy_planet.end(), train[id].v) - heavy_planet.begin()) < heavy_planet.size() && heavy_planet[p] == train[id].v){
          st[p].update_pos(id - planet[train[id].v].first + 1, dp[id]);
        }
      }
    }
    return dp[m - 1] >= LINF ? -1 : dp[m - 1];
  }
}
ll solve(int N, int M, int W, vector<int>T, vector<int>X, vector<int>Y, vector<int>A, vector<int>B, vector<int>C, vector<int>L, vector<int>R){
  n = N;
  m = M;
  swap(t, T);
  swap(x, X);
  swap(y, Y);
  swap(a, A);
  swap(b, B);
  swap(c, C);
  swap(l, L);
  swap(r, R);
  if((w = W) == 0){
    return sub2::solve();
  }
  if(w <= 10 && max({n, m, *max_element(a.begin(), a.end()), *max_element(b.begin(), b.end()), *max_element(l.begin(), l.end()), *max_element(r.begin(), r.end())}) <= 1000){
    return sub1::solve();
  }
  return sub34::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...