Submission #1009766

#TimeUsernameProblemLanguageResultExecution timeMemory
1009766rxlfd314Train (APIO24_train)C++17
100 / 100
814 ms178888 KiB
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx2")
#include "train.h"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ari2 = array<int, 2>;
using arl2 = array<ll, 2>;

#define vt vector
#define size(x) (int((x).size()))
#define all(x) begin(x), end(x)

#define REP(a,b,c,d) for(int a=(b);(d)>0?a<=(c):a>=(c);a+=(d))
#define FOR(a,b,c) REP(a,b,c,1)
#define ROF(a,b,c) REP(a,b,c,-1)

constexpr int mxN = 100005;
constexpr ll INF = 0x3f3f3f3f3f3f3f3f;

struct Node {
  int val;
  Node *lft, *rht;
  Node(int v) : val(v), lft(nullptr), rht(nullptr) {}
  Node(Node *l, Node *r) : val(l->val + r->val), lft(l), rht(r) {}
  Node(Node *n) : val(n->val), lft(n->lft), rht(n->rht) {}
};

vt<int> cmp_l, cmp_r;

Node *sts[mxN<<1];

Node *build(int tl = 0, int tr = size(cmp_r)-1) {
  if (tl == tr)
    return new Node(0);
  int tm = tl + tr >> 1;
  return new Node(build(tl, tm), build(tm+1, tr));
}

Node *update(Node *n, int p, int v, int tl = 0, int tr = size(cmp_r)-1) {
  if (tl == tr)
    return new Node(n->val + v);
  int tm = tl + tr >> 1;
  if (p <= tm)
    return new Node(update(n->lft, p, v, tl, tm), n->rht);
  return new Node(n->lft, update(n->rht, p, v, tm+1, tr));
}

int query(Node *n, int ql, int qr, int tl = 0, int tr = size(cmp_r)-1) {
  if (tl > qr || tr < ql)
    return 0;
  if (ql <= tl && tr <= qr)
    return n->val;
  int tm = tl + tr >> 1;
  return query(n->lft, ql, qr, tl, tm) + query(n->rht, ql, qr, tm+1, tr);
}

struct Line {
  int l, m;
  ll c;
  ll eval(int x) {
    return 1ll * m * query(sts[l], 0, x) + c;
  }
};

struct Lichao {
  Line line;
  Lichao *lft, *rht;
  void update(Line new_line, int tl = 0, int tr = size(cmp_r)-1) {
    int tm = tl + tr >> 1;
    if (make_pair(new_line.eval(tm), -new_line.l) < make_pair(line.eval(tm), -line.l))
      swap(new_line, line);
    if (tl == tr)
      return;
    if (new_line.eval(tl) < line.eval(tl)) {
      if (!lft) {
        lft = new Lichao();
        lft->line = {0, 0, LLONG_MAX};
        lft->lft = lft->rht = nullptr;
      }
      lft->update(new_line, tl, tm);
    } else {
      if (!rht) {
        rht = new Lichao();
        rht->line = {0, 0, LLONG_MAX};
        rht->lft = rht->rht = nullptr;
      }
      rht->update(new_line, tm+1, tr);
    }
  }
  ll query(int x, int tl = 0, int tr = size(cmp_r)-1) {
    ll ret = line.eval(x);
    int tm = tl + tr >> 1;
    if (x <= tm)
      return min(ret, lft ? lft->query(x, tl, tm) : ret);
    return min(ret, rht ? rht->query(x, tm+1, tr) : ret);
  }
};

vt<ari2> adj[mxN*2];
vt<int> ins[mxN*2];
int node[mxN*2], times[mxN*2], ord[mxN*2];
Lichao *lcts[mxN];
ll dp[mxN*2];

ll solve(int N, int M, int W, vt<int> T, vt<int> X, vt<int> Y,
                              vt<int> A, vt<int> B, vt<int> C, vt<int> L, vt<int> R) {
  map<ari2, int> ind;
  ind[{0, 0}] = 0;
  FOR(i, 0, M-1) {
    int x = X[i], y = Y[i], a = A[i], b = B[i];
    if (ind.find({x, a}) == end(ind))
      ind[{x, a}] = size(ind);
    if (ind.find({y, b}) == end(ind))
      ind[{y, b}] = size(ind);
  }
  
  const int K = size(ind);
  FOR(i, 0, M-1) {
    int a = ind[{X[i], A[i]}];
    int b = ind[{Y[i], B[i]}];
    node[a] = X[i], times[a] = A[i];
    node[b] = Y[i], times[b] = B[i];
    adj[a].push_back({b, C[i]});
  }
  
  {
    cmp_l.push_back(0);
    cmp_r.push_back(0);
    FOR(i, 0, W-1) {
      cmp_l.push_back(L[i]);
      cmp_r.push_back(R[i]);
    }
    
    sort(all(cmp_l));
    cmp_l.erase(unique(all(cmp_l)), end(cmp_l));
    sort(all(cmp_r));
    cmp_r.erase(unique(all(cmp_r)), end(cmp_r));
    
    FOR(i, 0, W-1) {
      ins[lower_bound(all(cmp_l), L[i]) - begin(cmp_l)].push_back(lower_bound(all(cmp_r), R[i]) - begin(cmp_r));
    }
    sts[size(cmp_l)] = build();
    ROF(i, size(cmp_l)-1, 0) {
      sts[i] = new Node(sts[i+1]);
      for (int j : ins[i])
        sts[i] = update(sts[i], j, 1);
    }
  }
  
  iota(ord, ord+K, 0);
  sort(ord, ord+K, [&](const int &a, const int &b) {
    return times[a] < times[b];    
  });
  
  memset(dp, 0x3f, K<<3);
  FOR(i, 0, N-1) {
    lcts[i] = new Lichao();
    lcts[i]->line = {0, 0, LLONG_MAX};
    lcts[i]->lft = lcts[i]->rht = nullptr;
  }
  dp[0] = 0;
  ll ans = INF;
  for (int i : ord) {
    ll go = lcts[node[i]]->query(lower_bound(all(cmp_r), times[i]) - begin(cmp_r) - 1);
    if (min(go, dp[i]) < INF)
      for (auto [j, v] : adj[i])
        dp[j] = min(dp[j], min(go, dp[i]) + v);
    int j = upper_bound(all(cmp_l), times[i]) - begin(cmp_l);
    if (dp[i] < INF)
      lcts[node[i]]->update({j, T[node[i]], dp[i]});
    if (node[i] == N-1 && dp[i] < INF)
      ans = min(ans, dp[i] + 1ll * T[node[i]] * (j < size(cmp_l) ? sts[j]->val : 0));
  }
  
  return ans < INF ? ans : -1;
}

Compilation message (stderr)

train.cpp: In function 'Node* build(int, int)':
train.cpp:36:15: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   36 |   int tm = tl + tr >> 1;
      |            ~~~^~~~
train.cpp: In function 'Node* update(Node*, int, int, int, int)':
train.cpp:43:15: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   43 |   int tm = tl + tr >> 1;
      |            ~~~^~~~
train.cpp: In function 'int query(Node*, int, int, int, int)':
train.cpp:54:15: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   54 |   int tm = tl + tr >> 1;
      |            ~~~^~~~
train.cpp: In member function 'void Lichao::update(Line, int, int)':
train.cpp:70:17: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   70 |     int tm = tl + tr >> 1;
      |              ~~~^~~~
train.cpp: In member function 'll Lichao::query(int, int, int)':
train.cpp:93:17: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   93 |     int tm = tl + tr >> 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...