Submission #1259985

#TimeUsernameProblemLanguageResultExecution timeMemory
1259985antromancapTrain (APIO24_train)C++20
100 / 100
198 ms48900 KiB
#include <bits/stdc++.h>

using namespace std;

const long long inf = 1e18;
const int N = 1e5 + 1;
int n, m, w, cost[N], meal2[N], cnt = 0, cur = 0;
long long dist[N];
set<pair<long long, int>> city[N];
vector<int> g[N];
priority_queue<pair<int, int>> q;
int rt[N], ls[30 * N], rs[30 * N], it[30 * N];

struct Edge {
	int x, y, a, b, c;
	bool operator<(const Edge &u) const { return a < u.a; }
} e[N];

struct Meal {
	int l, r, id;
} meal[N];

bool cmp1(const Meal &x, const Meal &y) { return make_pair(x.r, x.l) < make_pair(y.r, y.l); }
bool cmp2(const Meal &x, const Meal &y) { return x.l < y.l; }

void upd(int i, int old, int l, int r, int p) {
	it[i] = it[old] + 1;
	if (l == r) return;
	int mid = (l + r) >> 1;
	if (p <= mid) {
		rs[i] = rs[old];
		upd(ls[i] = ++cnt, ls[old], l, mid, p);
	} else {
		ls[i] = ls[old];
		upd(rs[i] = ++cnt, rs[old], mid + 1, r, p);
	}
}

int query(int i, int l, int r, int u, int v) {
	if (!i || l > v || r < u) return 0;
	if (u <= l && r <= v) return it[i];
	int mid = (l + r) >> 1;
	return query(ls[i], l, mid, u, v) + query(rs[i], mid + 1, r, u, v);
}

long long getval(int i) {
	long long res = dist[i];
	if (cur == 0) return res;
	int p = upper_bound(meal2, meal2 + w, e[i].b) - meal2;
	long long cnt = cur;
	if (p) cnt -= query(rt[p - 1], 0, w - 1, 0, cur - 1);
	assert(cnt >= 0);
	return res + cnt * cost[e[i].y];
}

int findkth(int i, int j, int l, int r, int k) {
	if (l == r) return l;
	int mid = (l + r) >> 1, t = it[ls[j]] - it[ls[i]];
	if (k <= t) return findkth(ls[i], ls[j], l, mid, k);
	return findkth(rs[i], rs[j], mid + 1, r, k - t);
}

int getkth(int l, int r, long long k) {
	l = lower_bound(meal2, meal2 + w, l) - meal2;
	r = upper_bound(meal2, meal2 + w, r) - meal2;
	if (!r || r - l < k) return -1;
	return findkth(l ? rt[l - 1] : 0, rt[r - 1], 0, w - 1, k);
}

void calc(int i) {
	int v = e[i].y;
	int j = prev(city[v].find(make_pair(dist[i], i)))->second;
	long long dif = dist[i] - dist[j];
	long long k = (dif + cost[v] - 1) / cost[v];
	int kth = getkth(e[j].b + 1, e[i].b, k);
	if (kth != -1) g[kth].push_back(i), assert(kth >= cur);
}

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;
	for (int i = 0; i < n; i++) cost[i] = T[i];
	for (int i = 0; i < m; i++) e[i] = { X[i], Y[i], A[i], B[i], C[i] };
	sort(e, e + m);
	for (int i = 0; i < w; i++) meal[i] = { L[i], R[i], 0 };
	sort(meal, meal + w, cmp1);
	for (int i = 0; i < w; i++) meal[i].id = i;
	sort(meal, meal + w, cmp2);
	for (int i = 0; i < w; i++) {
		upd(rt[i] = ++cnt, i ? rt[i - 1] : 0, 0, w - 1, meal[i].id);
		meal2[i] = meal[i].l;
	}
	sort(meal, meal + w, cmp1);
	memset(dist, -1, 8 * m);
	city[0].insert(make_pair(0, m));
	e[m].b = -1;
	bool ok = 0;
	for (int i = 0; i < m; i++) {
		if (i == 250) ok = 1;
		while (cur < w && meal[cur].r < e[i].a) {
			cur++;
			for (int j : g[cur - 1]) {
				int v = e[j].y;
				auto it = city[v].find(make_pair(dist[j], j));
				if (it == city[v].end()) continue;
				while (it != city[v].begin() && getval(prev(it)->second) >= getval(j)) city[v].erase(prev(it));
				if (it != city[v].begin()) calc(j);
			}
		}
		while (q.size() && -q.top().first <= e[i].a) {
			int j = q.top().second;
			q.pop();
			int v = e[j].y;
			while (city[v].size() && getval(city[v].rbegin()->second) >= getval(j)) city[v].erase(--city[v].end());
			city[v].insert(make_pair(dist[j], j));
			if (city[v].size() > 1) calc(j);
		}
		int u = e[i].x;
		if (city[u].empty()) continue;
		dist[i] = getval(city[u].begin()->second) + e[i].c;
		q.push(make_pair(-e[i].b, i));
	}

	cur = w;
	long long res = inf;
	for (int i = 0; i < m; i++)
		if (e[i].y == n - 1 && dist[i] != -1) res = min(res, getval(i));
	return res < inf ? res : -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...