Submission #991203

#TimeUsernameProblemLanguageResultExecution timeMemory
991203model_codeTrain (APIO24_train)C++17
100 / 100
227 ms83584 KiB
#include "train.h"

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;

#define F first
#define S second
#define pii pair<LL, LL>
#define pb push_back
#define pq priority_queue
#define rep(i,a,b) for (long long i=a; i < (b); i++)
#define MP make_pair
#define SZ(x) (static_cast<long long>(x.size()))
#define MOD 1000000007LL

const long long maxn = 1e5 + 10;

long long n, m, w, tot = 0;
pair <pii, long long> meal[maxn];
pair <pii, long long> meal_copy[maxn];
long long c[maxn];
vector <long long> neg[maxn];
struct Train{
  long long x, y, a, b, c;
} train[maxn];

bool cmp(pair<pii, long long> i1, pair<pii, long long> i2) {
  return MP(i1.F.S, i1.F.F) < MP(i2.F.S, i2.F.F);
}

bool cmp1(Train i1, Train i2) {
  return i1.a < i2.a;
}

long long dist[maxn];
vector <long long> city[maxn], lst[maxn];
long long id[maxn], bg[maxn], ed[maxn];
pq <pii, vector<pii>, greater<pii> > q;
bool mark[maxn];
long long curmeal = 0;

//persistnet segtree
long long rt[maxn], lc[maxn * 100], rc[maxn * 100], val[maxn * 100];

long long query(long long c, long long cl, long long cr, long long l, long long r) {
  if (l <= cl and cr <= r) return val[c];
  long long mid = cl + cr >> 1;
  long long ret = 0;
  if (l <= mid) ret = query(lc[c], cl, mid, l, r);
  if (r > mid) ret += query(rc[c], mid + 1, cr, l, r);
  return ret;
}

long long getval(long long t) { //dist + # meals strictly after the current long longerval
  long long ret = dist[t];
  if (curmeal == 0) return ret;
  long long cnt = curmeal;
  long long pos = upper_bound(meal_copy, meal_copy + w, MP(MP(train[t].b, MOD), MOD)) - meal_copy;
  if (pos > 0) cnt -= query(rt[pos - 1], 0, w - 1, 0, curmeal - 1);
  ret += cnt * c[train[t].y];
  return ret;
}

long long findKth(long long c1, long long c2, long long cl, long long cr, long long K) {
  if (cl == cr) return cl;
  long long mid = cl + cr >> 1;
  long long tmp = val[lc[c2]] - val[lc[c1]];
  if (K <= tmp) return findKth(lc[c1], lc[c2], cl, mid, K);
  K -= tmp;
  return findKth(rc[c1], rc[c2], mid + 1, cr, K);
}

long long getKth(long long l, long long r, long long K) {
  long long bg = lower_bound(meal_copy, meal_copy + w, MP(MP(l, -1LL), -1LL)) - meal_copy;
  long long ed = upper_bound(meal_copy, meal_copy + w, MP(MP(r, MOD), MOD)) - meal_copy;
  if (ed == 0 or ed - bg < K) return -1;
  return findKth((bg == 0 ? 0 : rt[bg - 1]), rt[ed - 1], 0, w - 1, K);
}

long long init(long long cl, long long cr) {
  if (cl == cr) {
    val[tot] = 0;
    return tot++;
  }
  long long tmp = tot, mid = cl + cr >> 1;
  lc[tmp] = init(cl, mid);
  rc[tmp] = init(mid + 1, cr);
  val[tmp] = 0;
  return tmp;
}

void calc(long long t) {
  long long tmp = train[t].y;
  long long tt = city[tmp][lst[tmp][id[t]]];
  long long dif = dist[t] - dist[tt];
  long long K = (dif + c[tmp] - 1) / c[tmp];
  long long val = getKth(train[tt].b + 1, train[t].b, K);
  if (val != -1) neg[val].pb(t), assert(val >= curmeal);
}

void update(long long c, long long cl, long long cr, long long pos) {
  val[c]++;
  if (cl == cr) return;
  long long mid = cl + cr >> 1;
  if (pos <= mid) {
    lc[tot] = lc[lc[c]];
    rc[tot] = rc[lc[c]];
    val[tot] = val[lc[c]];
    lc[c] = tot++;
    update(lc[c], cl, mid, pos);
  } else {
    lc[tot] = lc[rc[c]];
    rc[tot] = rc[rc[c]];
    val[tot] = val[rc[c]];
    rc[c] = tot++;
    update(rc[c], mid + 1, cr, pos);
  }
}

long long 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, w = W;
  rep(i, 0, n) c[i] = t[i];
  rep(i, 0, m)
    train[i].x = X[i], train[i].y = Y[i], train[i].a = A[i], train[i].b = B[i], train[i].c = C[i];
  rep(i, 0, w) meal[i].F = {L[i], R[i]};
  sort(meal, meal + w, cmp); //sorted by increasing B for processing
  rep(i, 0, w) {
    meal[i].S = i;
    meal_copy[i] = meal[i];
  }
  sort(meal_copy, meal_copy + w); //sorted by increasing A for segtree
  if (w > 0) init(0, w - 1);
  rep(i, 0, w) {
    rt[i] = tot;
    lc[tot] = (i > 0 ? lc[rt[i - 1]] : lc[0]);
    rc[tot] = (i > 0 ? rc[rt[i - 1]] : rc[0]);
    val[tot] = (i > 0 ? val[rt[i - 1]] : 0);
    update(tot++, 0, w - 1, meal_copy[i].S);
  }
  memset(dist, -1, sizeof(dist));
  sort(train, train + m, cmp1);
  memset(ed, -1, sizeof(ed));
  city[0].pb(m);
  lst[0].pb(-1);
  dist[m] = 0;
  train[m].y = 0, train[m].b = -1;
  bg[0] = ed[0] = 0;
  rep(i, 0, m) {
    long long X = train[i].x;    
    while (curmeal < w and meal[curmeal].F.S < train[i].a) { //look at meals
      long long cur = curmeal++;
      for (auto it : neg[cur]) {
        if (mark[it]) continue;
	    long long tmp = train[it].y;
	    if (id[it] == bg[tmp]) continue;
	    assert(lst[tmp][id[it]] != -1);
	    while (getval(city[tmp][lst[tmp][id[it]]]) >= getval(it)) {
	      mark[city[tmp][lst[tmp][id[it]]]] = 1;
	      if (lst[tmp][id[it]] == bg[tmp]) {
	        bg[tmp] = id[it];
	        break;
	      } else lst[tmp][id[it]] = lst[tmp][lst[tmp][id[it]]];
	    }
	    if (bg[tmp] != id[it]) calc(it);
      }
    }
    while (!q.empty() and q.top().F <= train[i].a) {
      long long cur = q.top().S;
      q.pop();
      long long tmp = train[cur].y;
      while (bg[tmp] <= ed[tmp] and getval(city[tmp][ed[tmp]]) >= getval(cur)) {
	    if (bg[tmp] == ed[tmp]) {
	      bg[tmp] = SZ(city[tmp]);
	      break;
	    }
	    mark[city[tmp][ed[tmp]]] = 1;
	    ed[tmp] = lst[tmp][ed[tmp]];
      }
      if (bg[tmp] > ed[tmp]) {
        id[cur] = bg[tmp] = ed[tmp] = SZ(city[tmp]);
	    city[tmp].pb(cur);
	    lst[tmp].pb(-1);
      } else {
	    id[cur] = SZ(city[tmp]);
	    city[tmp].pb(cur);
	    lst[tmp].pb(ed[tmp]);
	    ed[tmp] = id[cur];
	    calc(cur);
      }
    }
    
    if (bg[X] > ed[X]) continue;
    dist[i] = getval(city[X][bg[X]]) + train[i].c;
    q.push({train[i].b, i});
  }
  curmeal = w;
  long long ans = 1e18;
  rep(i, 0, m) if (train[i].y == n - 1 and dist[i] != -1)
    ans = min(ans, getval(i));
  if (ans < 1e18) return ans;
  else return -1;
}

Compilation message (stderr)

train.cpp: In function 'long long int query(long long int, long long int, long long int, long long int, long long int)':
train.cpp:49:22: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   49 |   long long mid = cl + cr >> 1;
      |                   ~~~^~~~
train.cpp: In function 'long long int findKth(long long int, long long int, long long int, long long int, long long int)':
train.cpp:68:22: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   68 |   long long mid = cl + cr >> 1;
      |                   ~~~^~~~
train.cpp: In function 'long long int init(long long int, long long int)':
train.cpp:87:33: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   87 |   long long tmp = tot, mid = cl + cr >> 1;
      |                              ~~~^~~~
train.cpp: In function 'void update(long long int, long long int, long long int, long long int)':
train.cpp:106:22: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  106 |   long long mid = cl + cr >> 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...