Submission #219181

# Submission time Handle Problem Language Result Execution time Memory
219181 2020-04-04T06:21:24 Z atoiz Sweeping (JOI20_sweeping) C++14
Compilation error
0 ms 0 KB
/*input
8 1 8
1 5
4 4 1
2 6
1 2
2 3
4 2 2
2 5
1 1
1 3
*/

#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>

using namespace std;

const int MAXN = 1500007, INF = 1e9 + 8;
int N, M, Q;
pair<int, int> ans[MAXN];
#define x first
#define y second

void minimize(int &x, int y) { x = (x < y ? x : y); }
void maximize(int &x, int y) { x = (x > y ? x : y); }

struct Event
{
	int type, x, id;
} events[MAXN];

struct SegmentTree
{
	int N;
	vector<int> val, lazy;
	
	void init(int _N, int x = -1)
	{
		N = _N;
		val.assign(N << 2, x);
		lazy.assign(N << 2, x);
	}

	void pushdown(int rt)
	{
		if (~lazy[rt]) {
			maximize(val[rt << 1], lazy[rt]);
			maximize(val[rt << 1 | 1], lazy[rt]);
			maximize(lazy[rt << 1], lazy[rt]);
			maximize(lazy[rt << 1 | 1], lazy[rt]);
			lazy[rt] = -1;
		}
	}

	void modify(int l, int r, int x, int rt, int lo, int hi)
	{
		if (hi < l || r < lo) return;
		if (l <= lo && hi <= r) return maximize(val[rt], x), maximize(lazy[rt], x);

		pushdown(rt);
		int md = (lo + hi) >> 1;
		modify(l, r, x, rt << 1, lo, md);
		modify(l, r, x, rt << 1 | 1, md + 1, hi);
	}
	void modify(int l, int r, int x)
	{
		modify(l, r, x, 1, 0, N - 1);
	}

	int get(int i, int rt, int lo, int hi)
	{
		if (lo == hi) return val[rt];
		pushdown(rt);
		int md = (lo + hi) >> 1;
		if (i <= md) return get(i, rt << 1, lo, md);
		else return get(i, rt << 1 | 1, md + 1, hi);
	}
	int get(int i)
	{
		return get(i, 1, 0, N - 1);
	}
} st_h, st_v;

struct DSU
{	
	int N = 0;
	vector<int> dsu, lo, hi;

	void init(int _N)
	{
		N = _N;
		dsu.resize(N), lo.resize(N), hi.resize(N);
		for (int i = 0; i < N; ++i) dsu[i] = -1, lo[i] = i, hi[i] = i + 1;
	}

	int root(int x) { return (dsu[x] < 0 ? x : dsu[x] = root(dsu[x])); }
	void join(int x, int y)
	{
		x = root(x), y = root(y);
		if (x == y) return;
		if (dsu[x] > dsu[y]) swap(x, y);
		dsu[x] += dsu[y];
		dsu[y] = x;
		minimize(lo[x], lo[y]);
		maximize(hi[x], hi[y]);
	}
	pair<int, int> get(int id) { return id = root(id), make_pair(lo[id], hi[id]); }
} dsu;

pair<int, int> cur_pos[MAXN];
vector<int> pos_x, rem, seg_h, seg_v, dusts, group;
vector<pair<int, int>> tmp_pos;
vector<vector<int>> segs_h;
void solve(int lo, int hi)
{
	if (lo == hi) return;
	int mid = (lo + hi) >> 1;
	solve(lo, mid), solve(mid + 1, hi);

	// identify dust IDs
	int from_id = INF, to_id = 0;
	for (int i = lo; i <= mid; ++i) {
		if (events[i].type == 4) {
			minimize(from_id, events[i].id);
			maximize(to_id, events[i].id);
		}
	}
	if (from_id > to_id) return;
	// cout << "\nrange " << lo << ' ' << hi << endl;

	// identify pos_x
	pos_x.clear(), pos_x.push_back(-1);
	for (int i = mid + 1; i <= hi; ++i) {
		if (events[i].type == 2 || events[i].type == 3) {
			pos_x.push_back(events[i].x);		
		}
	}
	sort(pos_x.begin(), pos_x.end()), pos_x.erase(unique(pos_x.begin(), pos_x.end()), pos_x.end());
	auto get_x = [&](int x) -> int { return int(lower_bound(pos_x.begin(), pos_x.end(), x) - pos_x.begin()); };
	int X = (int) pos_x.size();
	pos_x.push_back(N);
	// cout << "pos_x "; for (int x : pos_x) cout << x << ' '; cout << endl;

	// find segments
	rem.assign(hi - mid, -1);
	seg_h.assign(X + 1, -1), seg_v.assign(X + 1, -1);
	st_h.init(X, -1), st_v.init(X, -1);
	segs_h.assign(X + 1, vector<int>(0));
	for (int i = mid + 1; i <= hi; ++i) {
		if (events[i].type == 2) {
			int x = get_x(events[i].x);
			int p = get_x(st_h.get(x));
			if (p == x) continue;
			assert(p < x);

			if (!~seg_h[x]) {
				rem[i - (mid + 1)] = x;
				seg_h[x] = p;
				segs_h[p + 1].push_back(x);
				st_v.modify(p + 1, x, N - events[i].x);
			}
		} else if (events[i].type == 3) {
			int x = get_x(events[i].x);
			int p = get_x(N - st_v.get(x));
			if (p == x) continue;
			assert(p > x);

			if (!~seg_v[x]) {
				rem[i - (mid + 1)] = x;
				seg_v[x] = p;
				st_h.modify(x, p - 1, events[i].x);
			}
		}
	}

	// find dusts
	dusts.resize(to_id - from_id + 1);
	iota(dusts.begin(), dusts.end(), from_id);
	sort(dusts.begin(), dusts.end(), [&](int i, int j) { return cur_pos[i].x < cur_pos[j].x; });

	// sort dusts into dsu groups
	group.assign(to_id - from_id + 1, -1);
	st_v.init(X + 1, 0);
	dsu.init(X);
	vector<int>::iterator dust_it = dusts.begin();
	for (int x = 0; x <= X; ++x) {
		for (int x1 : segs_h[x]) {
			// cout << "horizontal " << x1 << endl;
			st_v.modify(x1 + 1, X, x1);
		}

		for (; dust_it != dusts.end() && cur_pos[*dust_it].x <= pos_x[x]; ++dust_it) {
			int id = *dust_it;
			group[id - from_id] = st_v.get(get_x(N - cur_pos[id].y));
			// cout << "group " << id << ": " << group[id - from_id] << " | " << N - cur_pos[id].y << endl;
		}

		if (~seg_v[x]) {
			// cout << "vertical " << x << ": " << seg_v[x] << endl;
			st_v.modify(x + 1, seg_v[x], x);
		}
	}
	assert(dust_it == dusts.end());

	// calc final pos
	auto get_pos = [&](pair<int, int> pnt, int g) -> pair<int, int> {
		pair<int, int> lim = dsu.get(g);
		maximize(pnt.first, pos_x[lim.first] + 1);
		minimize(pnt.first, pos_x[lim.second]);
		maximize(pnt.second, N - pos_x[lim.second]);
		minimize(pnt.second, N - pos_x[lim.first] - 1);
		return pnt;
	};
	tmp_pos.resize(to_id - from_id + 1);
	for (int i = from_id; i <= to_id; ++i) {
		tmp_pos[i - from_id] = cur_pos[i];
		// cout << cur_pos[i].x << ' ' << cur_pos[i].y << " -> ";
		cur_pos[i] = get_pos(tmp_pos[i - from_id], group[i - from_id]);
		// cout << cur_pos[i].x << ' ' << cur_pos[i].y;
		// auto x = dsu.get(group[i - from_id]); cout << " = " << pos_x[x.x] << ' ' << pos_x[x.y] << endl;
	}

	for (int i = hi; i >= mid + 1; --i) {
		if (events[i].type == 1 && events[i].x >= from_id && events[i].x <= to_id) {
			int dust_id = events[i].x;
			// cout << "ans " << events[i].id << ": " << dust_id << " _ " << tmp_pos[dust_id - from_id].x << ' ' << tmp_pos[dust_id - from_id].y << " -> ";
			cout << flush;
			ans[events[i].id] = get_pos(tmp_pos[dust_id - from_id], group[dust_id - from_id]);
			// cout << ans[events[i].id].x << ' ' << ans[events[i].id].y;
			// auto x = dsu.get(group[dust_id - from_id]); cout << " = " << pos_x[x.x] << ' ' << pos_x[x.y] << endl;
		} else if (~rem[i - (mid + 1)]) {
			int x = rem[i - (mid + 1)];
			// cout << "rem " << i << ": " << x << endl;
			dsu.join(x - 1, x);
		}
	}
}

int main()
{
	ios_base::sync_with_stdio(0); cin.tie(0);
	cin >> N >> M >> Q;
	int num_events = 0, num_dusts = 0, num_questions = 0;
	for (int i = 0; i < M; ++i) {
		auto &cur = events[++num_events];
		cur.type = 4;
		cur.id = ++num_dusts;
		cin >> cur_pos[cur.id].first >> cur_pos[cur.id].second;
	}

	for (int i = 0; i < Q; ++i) {
		auto &cur = events[++num_events];
		cin >> cur.type;
		if (cur.type == 1) {
			cin >> cur.x;
			cur.id = ++num_questions;
		} else if (cur.type == 2) {
			cin >> cur.x;
			cur.x = N - cur.x - 1;
		} else if (cur.type == 3) {
			cin >> cur.x;
		} else {
			cur.id = ++num_dusts;
			cin >> cur_pos[cur.id].first >> cur_pos[cur.id].second;
		}
	}

	solve(1, num_events);
	for (int i = 1; i <= num_questions; ++i) {
		cout << ans[i].first << ' ' << ans[i].second << '\n';
	}
}

Compilation message

sweeping.cpp: In function 'void solve(int, int)':
sweeping.cpp:181:2: error: 'iota' was not declared in this scope
  iota(dusts.begin(), dusts.end(), from_id);
  ^~~~
sweeping.cpp:181:2: note: suggested alternative: 'int'
  iota(dusts.begin(), dusts.end(), from_id);
  ^~~~
  int