Submission #258082

# Submission time Handle Problem Language Result Execution time Memory
258082 2020-08-05T10:29:35 Z atoiz Sky Walking (IOI19_walk) C++14
25 / 100
4000 ms 81472 KB
#include "walk.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <tuple>
#include <cassert>
#include <numeric>
 
using namespace std;
using ll = long long;
 
const int MAXY = 1000100100;
const ll INFLL = 1e16;
int N, M, T;
vector<int> X, H, L, R, Y;
vector<int> valY;
 
int dist(int i, int j) { return abs(X[i] - X[j]); }
// int pos(int y) { return (int) (upper_bound(valY.begin(), valY.end(), y) - valY.begin() - 1); } // first <=
 
struct SegmentTree {
	vector<ll> lazy, arr;
	vector<int> cnt;
	SegmentTree(): lazy((T + 2) * 4, INFLL), arr((T + 2) * 4, INFLL), cnt((T + 2) * 4, 0) {}
 
	void push(int rt, int lo, int hi) {
		if (lazy[rt] != INFLL && cnt[rt]) {
			if (lo == hi) arr[lo] = min(arr[lo], lazy[rt]);
			else {
				int lc = rt << 1, rc = rt << 1 | 1;
				lazy[lc] = min(lazy[lc], lazy[rt]), lazy[rc] = min(lazy[rc], lazy[rt]);
			}
		}
		lazy[rt] = INFLL;
	}
 
	void insert(int y, ll c) {
		int rt = 1, lo = 0, hi = T - 1;
		while (true) {
			push(rt, lo, hi);
			++cnt[rt];
			if (lo == hi) {
				assert(valY[lo] == y);
				arr[lo] = min(arr[lo], c);
				break;
			}
			int md = (lo + hi) >> 1;
			(y <= valY[md]) ? (rt = rt << 1, hi = md) : (rt = rt << 1 | 1, lo = md + 1);
		}
	}
 
	void remove(int y) {
		int rt = 1, lo = 0, hi = T - 1;
		while (true) {
			push(rt, lo, hi);
			--cnt[rt];
			if (lo == hi) {
				if (cnt[rt] == 0) arr[lo] = INFLL;
				break;
			}
			int md = (lo + hi) >> 1;
			(y <= valY[md]) ? (rt = rt << 1, hi = md) : (rt = rt << 1 | 1, lo = md + 1);
		}
	}
 
	void minimize(int l, int r, ll c, int rt, int lo, int hi) {
		if (valY[hi] < l || r < valY[lo] || !cnt[rt] || lazy[rt] <= c) return;
		push(rt, lo, hi);
		if (l <= valY[lo] && valY[hi] <= r) return lazy[rt] = min(lazy[rt], c), void(0);
		int lc = rt << 1, rc = rt << 1 | 1, md = (lo + hi) >> 1;
		minimize(l, r, c, lc, lo, md), minimize(l, r, c, rc, md + 1, hi);
	}
	void minimize(int l, int r, ll c) { minimize(l, r, c, 1, 0, T - 1); }
 
	ll get(int l, int r, bool minY, int rt, int lo, int hi) {
		if (valY[hi] < l || r < valY[lo] || !cnt[rt]) return INFLL;
		push(rt, lo, hi);
		if (lo == hi) return arr[lo];
		int lc = rt << 1, rc = rt << 1 | 1, md = (lo + hi) >> 1;
 
		ll ans = INFLL;
		if (minY) {
			ans = get(l, r, minY, lc, lo, md);
			if (ans == INFLL) ans = get(l, r, minY, rc, md + 1, hi);
		} else {
			ans = get(l, r, minY, rc, md + 1, hi);
			if (ans == INFLL) ans = get(l, r, minY, lc, lo, md);
		}
		return ans;
	}
	ll get(int l, int r, bool minY) { return get(l, r, minY, 1, 0, T - 1); }
};
 
vector<vector<pair<int, ll>>> solve(int start) {
	// cout << "solve " << start << endl;
	vector<vector<pair<int, ll>>> ans(M);
 
	vector<vector<int>> walksAdd(N), walksRem(N);
	vector<int> walkL(M, -1), walkR(M, -1);
	vector<int> walkIDs(M);
	iota(walkIDs.begin(), walkIDs.end(), 0);
	sort(walkIDs.begin(), walkIDs.end(), [&](int i, int j) { return Y[i] < Y[j]; });
	vector<int> lCols, rCols;
	for (int x = 0; x <= start; lCols.push_back(x++)) while (!lCols.empty() && H[lCols.back()] <= H[x]) lCols.pop_back();
	for (int x = N - 1; x >= start; rCols.push_back(x--)) while (!rCols.empty() && H[rCols.back()] <= H[x]) rCols.pop_back();
	for (int w : walkIDs) {
		if (L[w] <= start && start <= R[w] && Y[w] <= H[start]) { 
			walksAdd[walkL[w] = walkR[w] = start].push_back(w);
			walksRem[L[w]].push_back(w), walksRem[R[w]].push_back(w);
			continue; 
		}
 
		while (!lCols.empty() && H[lCols.back()] < Y[w]) lCols.pop_back();
		while (!rCols.empty() && H[rCols.back()] < Y[w]) rCols.pop_back();
		if (!rCols.empty() && rCols.back() <= L[w]) walksAdd[L[w]].push_back(w), walksRem[R[w]].push_back(w);
		else if (!lCols.empty() && lCols.back() >= R[w]) walksAdd[R[w]].push_back(w), walksRem[L[w]].push_back(w);
		else {
			if (!lCols.empty() && L[w] <= lCols.back()) walksAdd[walkL[w] = lCols.back()].push_back(w), walksRem[L[w]].push_back(w);
			if (!rCols.empty() && R[w] >= rCols.back()) walksAdd[walkR[w] = rCols.back()].push_back(w), walksRem[R[w]].push_back(w);
		}
	}
 
	// for (int x = 0; x < N; ++x) {
	// 	cout << x << ":\n";
	// 	for (auto w : walksRem[x]) cout << L[w] << ' ' << R[w] << ' ' << Y[w] << endl;
	// }
 
	vector<vector<SegmentTree>> st(2, vector<SegmentTree>(2, SegmentTree()));
	for (int w : walksAdd[start]) {
		if (L[w] < start) st[0][0].insert(Y[w], 0), st[0][1].insert(Y[w], Y[w]);
		if (R[w] > start) st[1][0].insert(Y[w], 0), st[1][1].insert(Y[w], Y[w]);
		ans[w].emplace_back(start, 0);
	}
 
	vector<vector<pair<int, ll>>> updates(N);
	int leftBorder = start, rightBorder = start;
	while (leftBorder > 0 || rightBorder < N - 1) {
		ll leftBest = st[0][0].get(0, H[leftBorder], false), rightBest = st[1][0].get(0, H[rightBorder], false);
		bool k = leftBest > rightBest;
		if (leftBorder == 0) k = 1;
		if (rightBorder == N - 1) k = 0;
 
		int col = (k == 0 ? --leftBorder : ++rightBorder);
 
		for (int w : walksAdd[col]) {
			ll curCost = min(st[k][0].get(0, Y[w], false), st[k][1].get(Y[w], H[col], true) - Y[w]);
			if (curCost == INFLL - Y[w]) curCost = INFLL;
			st[k][0].insert(Y[w], curCost), st[k][1].insert(Y[w], curCost + Y[w]);
			// cout << "pre dist " << col << ' ' << Y[w] << ": " << curCost << endl;
		}
 
		// cout << "S" << endl;
		for (auto upd : updates[col]) {
			// cout << "." << endl;
			int y = upd.first;
			ll c = upd.second;
			st[k][0].minimize(y, H[col], c), st[k][1].minimize(0, y, c + y);
		}
		// cout << "T" << endl;
		for (int w : walksAdd[col]) {
			ll curCost = min(st[k][0].get(Y[w], Y[w], false), st[k][1].get(Y[w], Y[w], false) - Y[w]);
			if (curCost == INFLL - Y[w]) curCost = INFLL;
			// cout << "dist " << col << ' ' << Y[w] << ": " << curCost << endl;
			ans[w].emplace_back(col, curCost);
 
			if (~walkL[w] && ~walkR[w] && walkL[w] <= start && start <= walkR[w]) {
				if (col == walkL[w]) updates[walkR[w]].emplace_back(Y[w], curCost + X[start] - X[col]);
				if (col == walkR[w]) updates[walkL[w]].emplace_back(Y[w], curCost + X[col] - X[start]);
			}
		}
 
		for (int w : walksRem[col]) st[k][0].remove(Y[w]), st[k][1].remove(Y[w]);
	}
 
	return ans;
}
 
ll min_distance(vector<int> x, vector<int> h, vector<int> l, vector<int> r, vector<int> y, int s, int t) {
	N = (int) x.size(), M = (int) y.size();
	X = x, H = h, L = l, R = r, Y = y;
	valY = Y;
	sort(valY.begin(), valY.end()), valY.erase(unique(valY.begin(), valY.end()), valY.end());
	T = (int) valY.size();
 
	vector<vector<pair<int, ll>>> ansS = solve(s);
	vector<vector<pair<int, ll>>> ansT = solve(t);
	ll ans = INFLL;
	for (int j = 0; j < M; ++j) {
		for (auto p : ansS[j]) for (auto q : ansT[j]) {
			ll cur = 0;
			cur += (ll) Y[j] * 2;
			cur += (ll) dist(p.first, q.first) + dist(p.first, s) + dist(q.first, t);
			cur += (p.second + q.second) * 2;
			// if (cur == 27) cout << L[j] << ' ' << R[j] << ' ' << Y[j] << " - " << p.first << ' ' << q.first << endl;
			ans = min(ans, cur);
		}
	}
 
	if (ans == INFLL) ans = -1;
	return ans;
}
# Verdict Execution time Memory Grader output
1 Correct 1 ms 256 KB Output is correct
2 Correct 0 ms 256 KB Output is correct
3 Correct 1 ms 256 KB Output is correct
4 Correct 1 ms 256 KB Output is correct
5 Correct 0 ms 384 KB Output is correct
6 Correct 0 ms 384 KB Output is correct
7 Correct 1 ms 384 KB Output is correct
8 Correct 0 ms 384 KB Output is correct
9 Correct 0 ms 256 KB Output is correct
10 Correct 0 ms 384 KB Output is correct
11 Correct 0 ms 384 KB Output is correct
12 Correct 0 ms 384 KB Output is correct
13 Correct 0 ms 384 KB Output is correct
14 Correct 1 ms 384 KB Output is correct
15 Correct 1 ms 256 KB Output is correct
16 Correct 0 ms 384 KB Output is correct
17 Correct 0 ms 384 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 0 ms 256 KB Output is correct
2 Correct 0 ms 256 KB Output is correct
3 Correct 640 ms 70596 KB Output is correct
4 Incorrect 856 ms 80580 KB Output isn't correct
5 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 73 ms 9972 KB Output is correct
2 Correct 692 ms 69296 KB Output is correct
3 Correct 667 ms 70600 KB Output is correct
4 Correct 885 ms 79176 KB Output is correct
5 Correct 754 ms 77508 KB Output is correct
6 Correct 757 ms 79024 KB Output is correct
7 Correct 414 ms 44864 KB Output is correct
8 Correct 710 ms 81472 KB Output is correct
9 Correct 719 ms 80256 KB Output is correct
10 Correct 495 ms 51456 KB Output is correct
11 Correct 25 ms 5188 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 73 ms 9972 KB Output is correct
2 Correct 692 ms 69296 KB Output is correct
3 Correct 667 ms 70600 KB Output is correct
4 Correct 885 ms 79176 KB Output is correct
5 Correct 754 ms 77508 KB Output is correct
6 Correct 757 ms 79024 KB Output is correct
7 Correct 414 ms 44864 KB Output is correct
8 Correct 710 ms 81472 KB Output is correct
9 Correct 719 ms 80256 KB Output is correct
10 Correct 495 ms 51456 KB Output is correct
11 Correct 25 ms 5188 KB Output is correct
12 Correct 685 ms 70460 KB Output is correct
13 Execution timed out 4062 ms 73592 KB Time limit exceeded
14 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 256 KB Output is correct
2 Correct 0 ms 256 KB Output is correct
3 Correct 1 ms 256 KB Output is correct
4 Correct 1 ms 256 KB Output is correct
5 Correct 0 ms 384 KB Output is correct
6 Correct 0 ms 384 KB Output is correct
7 Correct 1 ms 384 KB Output is correct
8 Correct 0 ms 384 KB Output is correct
9 Correct 0 ms 256 KB Output is correct
10 Correct 0 ms 384 KB Output is correct
11 Correct 0 ms 384 KB Output is correct
12 Correct 0 ms 384 KB Output is correct
13 Correct 0 ms 384 KB Output is correct
14 Correct 1 ms 384 KB Output is correct
15 Correct 1 ms 256 KB Output is correct
16 Correct 0 ms 384 KB Output is correct
17 Correct 0 ms 384 KB Output is correct
18 Correct 0 ms 256 KB Output is correct
19 Correct 0 ms 256 KB Output is correct
20 Correct 640 ms 70596 KB Output is correct
21 Incorrect 856 ms 80580 KB Output isn't correct
22 Halted 0 ms 0 KB -