답안 #598717

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
598717 2022-07-18T19:22:48 Z GusterGoose27 무지개나라 (APIO17_rainbow) C++11
12 / 100
967 ms 484464 KB
#include <bits/stdc++.h>

using namespace std;

typedef vector<pair<int, vector<int>>> plist;
typedef pair<int, int> pii;

const int MAXN = 2e5+5;
set<int> serpx[MAXN]; // points
set<int> serpy_c[MAXN]; // corners
set<int> serp_c[MAXN]; // corners, (i, j) refers to bottom left of square i, j
vector<pii> rangesx[MAXN];
vector<pii> rangesy[MAXN];

bool valid(int x, int y, set<int> s[] = serp_c) {
	if (x < 0) return 0;
	return (s[x].find(y) != s[x].end());
}

bool adjy(int x, int y) {
	return valid(x, y, serpx) || valid(x-1, y, serpx);
}

bool adjx(int x, int y) {
	return valid(x, y, serpx) || valid(x, y-1, serpx);
}

bool xempty(int y, int x1, int x2) {
	return (serpy_c[y].lower_bound(x1) == serpy_c[y].upper_bound(x2));
}

bool yempty(int x, int y1, int y2) {
	return (serp_c[x].lower_bound(y1) == serp_c[x].upper_bound(y2));
}

int getxcc(int y, int x1, int x2) {
	int mn = -1;
	int mx = rangesy[y].size();
	while (mx > mn+1) {
		int cur = (mn+mx)/2;
		if (rangesy[y][cur].second < x1) mn = cur;
		else mx = cur;
	}
	int l = mn;
	mn = -1;
	mx = rangesy[y].size();
	while (mx > mn+1) {
		int cur = (mn+mx)/2;
		if (rangesy[y][cur].first > x2) mx = cur;
		else mn = cur;
	}
	return mx-l-1;
}

int getycc(int x, int y1, int y2) {
	int mn = -1;
	int mx = rangesx[x].size();
	while (mx > mn+1) {
		int cur = (mn+mx)/2;
		if (rangesx[x][cur].second < y1) mn = cur;
		else mx = cur;
	}
	int l = mn;
	mn = -1;
	mx = rangesx[x].size();
	while (mx > mn+1) {
		int cur = (mn+mx)/2;
		if (rangesx[x][cur].first > y2) mx = cur;
		else mn = cur;
	}
	return mx-l-1;
}

class intree {
public:
	int ymin, ymax;
	int xmin, xmax;
	int point_count = 0;
	int edge_net = 0;
	int u_cut = 0;
	int r_cut = 0;
	int sq_count = 0;
	intree *l = nullptr;
	intree *r = nullptr;
	intree(plist &vals, int y1, int y2, int lp, int rp) {
		ymin = y1;
		ymax = y2;
		xmin = vals[lp].first;
		xmax = vals[rp].first;
		if (lp == rp) make_spec(vals[lp].second);
		else {
			int m = (lp+rp)/2;
			l = new intree(vals, y1, y2, lp, m);
			r = new intree(vals, y1, y2, m+1, rp);
			merge(vals, m);
		}
	}
	void make_spec(vector<int> &vals) {
		point_count = vals.size();
		for (int v: vals) {
			if (adjx(xmin, v)) r_cut++;
			if (v < ymax) {
				if (adjy(xmin, v)) edge_net++;
				//if (valid(xmin, v, serpx)) r_cut--;
			}
		}
		if (vals.back() == ymax) {
			if (adjy(xmin, ymax)) u_cut++;
		}
		for (auto it = serpx[xmin].lower_bound(ymin); it != serpx[xmin].end() && (*it) <= ymax; it++) sq_count++;
	}
	void merge(plist &vals, int m) {
		point_count = l->point_count+r->point_count;
		edge_net = l->edge_net+r->edge_net+l->r_cut;
		u_cut = l->u_cut+r->u_cut;
		r_cut = r->r_cut;
		sq_count = l->sq_count+r->sq_count;
		// if (vals[m].first == vals[m+1].first && vals[m].second.back() == ymax && vals[m+1].second.back() == ymax) {
		// 	u_cut--;
		// }
	}
	int query(int x1, int x2, int uc, int dc) {
		if (xmin > x2 || xmax < x1) return 0;
		if (xmin >= x1 && xmax <= x2) {
			int lc = (xmin > x1);
			int rc = (xmax < x2);
			int ans = edge_net-point_count;
			if (rc) ans += r_cut;
			if (uc) ans += u_cut;
			return ans;
		}
		int lq = l->query(x1, x2, uc, dc);
		int rq = r->query(x1, x2, uc, dc);
		// if (lq == -1) return rq;
		// if (rq == -1) return lq;
		return lq+rq;
	}
	int query2(int x1, int x2) {
		if (xmin > x2 || xmax < x1) return 0;
		if (xmin >= x1 && xmax <= x2) {
			return sq_count;
		}
		return l->query2(x1, x2)+r->query2(x1, x2);
	}
};

class stree {
public:
	int ymin, ymax;
	plist vals;
	intree *curtree = nullptr;
	stree *l = nullptr;
	stree *r = nullptr;
	stree(int y1, int y2) {
		ymin = y1;
		ymax = y2;
		if (ymin == ymax) make_vals_spec();
		else {
			int m = (ymin+ymax)/2;
			l = new stree(y1, m);
			r = new stree(m+1, y2);
			merge_vals();
		}
		if (vals.empty()) return;
		curtree = new intree(vals, y1, y2, 0, vals.size()-1);
	}
	void make_vals_spec() {
		for (int x: serpy_c[ymin]) vals.push_back(pair<int, vector<int>>(x, {ymin}));
	}
	vector<int> merge_vec(vector<int> &a, vector<int> &b) {
		int g = 0;
		int h = 0;
		vector<int> v;
		while (g < a.size() || h < b.size()) {
			if (g == a.size()) {
				v.push_back(b[h++]);
				continue;
			}
			if (h == b.size()) {
				v.push_back(a[g++]);
				continue;
			}
			if (a[g] < b[h]) {
				v.push_back(a[g++]);
			}
			else v.push_back(b[h++]);
		}
		return v;
	}
	void merge_vals() {
		int a = 0;
		int b = 0;
		while (a < l->vals.size() || b < r->vals.size()) {
			if (a == l->vals.size()) {
				vals.push_back(r->vals[b++]);
				continue;
			}
			if (b == r->vals.size()) {
				vals.push_back(l->vals[a++]);
				continue;
			}
			if (l->vals[a].first == r->vals[b].first) {
				vals.push_back(pair<int, vector<int>>(l->vals[a].first, merge_vec(l->vals[a].second, r->vals[b].second)));
				a++; b++;
				continue;
			}
			if (l->vals[a].first < r->vals[b].first) {
				vals.push_back(l->vals[a++]);
			}
			else vals.push_back(r->vals[b++]);
		}
	}
	int query(int x1, int x2, int y1, int y2) {
		if (ymin > y2 || ymax < y1 || curtree == nullptr) return 0;
		if (ymin >= y1 && ymax <= y2) {
			return curtree->query(x1, x2, ymax < y2, ymin > y1);
		}
		int lq = l->query(x1, x2, y1, y2);
		int rq = r->query(x1, x2, y1, y2);
		// if (lq == -1) return rq;
		// if (rq == -1) return lq;
		return lq+rq;
	}
	int query2(int x1, int x2, int y1, int y2) {
		if (ymin > y2 || ymax < y1 || curtree == nullptr) return 0;
		if (ymin >= y1 && ymax <= y2) return curtree->query2(x1, x2);
		return l->query2(x1, x2, y1, y2)+r->query2(x1, x2, y1, y2);
	}
};

stree *tree;

void color(int r, int c) {
	serpx[r].insert(c);
	serpy_c[c].insert(r);
	serpy_c[c].insert(r+1);
	serpy_c[c+1].insert(r);
	serpy_c[c+1].insert(r+1);
	serp_c[r].insert(c);
	serp_c[r].insert(c+1);
	serp_c[r+1].insert(c);
	serp_c[r+1].insert(c+1);
}

void init(int t1, int t2, int sr, int sc, int m, char *s) {
	sr--; sc--;
	color(sr, sc);
	for (int i = 0; i < m; i++) {
		if (s[i] == 'N') sr--;
		if (s[i] == 'S') sr++;
		if (s[i] == 'W') sc--;
		if (s[i] == 'E') sc++;
		color(sr, sc);
	}
	tree = new stree(0, MAXN-1);
	pii prev;
	for (int x = 0; x < MAXN; x++) {
		prev = pii(-1, -1);
		for (int y: serp_c[x]) {
			if (prev.second == -1) prev = pii(y, y);
			else prev.second++;
			if (!adjy(x, y)) {
				rangesx[x].push_back(prev);
				prev = pii(-1, -1);
			}
		}
	}
	for (int y = 0; y < MAXN; y++) {
		prev = pii(-1, -1);
		for (int x: serpy_c[y]) {
			if (prev.second == -1) prev = pii(x, x);
			else prev.second++;
			if (!adjx(x, y)) {
				rangesy[y].push_back(prev);
				prev = pii(-1, -1);
			}
		}
	}
}

int colour(int x1, int y1, int x2, int y2) {
	x1--;
	y1--;
	int sqs = tree->query2(x1, x2-1, y1, y2-1);
	if (sqs == 0) return 1;
	int ans = tree->query(x1, x2, y1, y2)-sqs;
	//if (xempty(y1, x1, x2) && xempty(y2, x1, x2) && yempty(x1, y1, y2) && yempty(x2, y1, y2)) return ans+2;
	int cc = getxcc(y1, x1, x2)+getxcc(y2, x1, x2)+getycc(x1, y1, y2)+getycc(x2, y1, y2);
	cc -= valid(x1, y1);
	cc -= valid(x1, y2);
	cc -= valid(x2, y1);
	cc -= valid(x2, y2);
	return ans+cc+1;
}

// int main() {
// 	init(6, 4, 3, 3, 9, "NWESSWEWS");
// 	cout << colour(2, 3, 2, 3) << "\n";
// 	cout << colour(3, 2, 4, 4) << "\n";
// 	cout << colour(5, 3, 6, 4) << "\n";
// 	cout << colour(1, 2, 5, 3) << "\n";
// 	return 0;
// }

Compilation message

rainbow.cpp: In member function 'int intree::query(int, int, int, int)':
rainbow.cpp:125:8: warning: unused variable 'lc' [-Wunused-variable]
  125 |    int lc = (xmin > x1);
      |        ^~
rainbow.cpp: In member function 'std::vector<int> stree::merge_vec(std::vector<int>&, std::vector<int>&)':
rainbow.cpp:174:12: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  174 |   while (g < a.size() || h < b.size()) {
      |          ~~^~~~~~~~~~
rainbow.cpp:174:28: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  174 |   while (g < a.size() || h < b.size()) {
      |                          ~~^~~~~~~~~~
rainbow.cpp:175:10: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  175 |    if (g == a.size()) {
      |        ~~^~~~~~~~~~~
rainbow.cpp:179:10: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  179 |    if (h == b.size()) {
      |        ~~^~~~~~~~~~~
rainbow.cpp: In member function 'void stree::merge_vals()':
rainbow.cpp:193:12: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, std::vector<int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  193 |   while (a < l->vals.size() || b < r->vals.size()) {
      |          ~~^~~~~~~~~~~~~~~~
rainbow.cpp:193:34: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, std::vector<int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  193 |   while (a < l->vals.size() || b < r->vals.size()) {
      |                                ~~^~~~~~~~~~~~~~~~
rainbow.cpp:194:10: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, std::vector<int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  194 |    if (a == l->vals.size()) {
      |        ~~^~~~~~~~~~~~~~~~~
rainbow.cpp:198:10: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, std::vector<int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  198 |    if (b == r->vals.size()) {
      |        ~~^~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 43 ms 63212 KB Output is correct
2 Correct 43 ms 64112 KB Output is correct
3 Incorrect 40 ms 63348 KB Output isn't correct
4 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 38 ms 62924 KB Output is correct
2 Correct 39 ms 62828 KB Output is correct
3 Correct 586 ms 130160 KB Output is correct
4 Correct 957 ms 175688 KB Output is correct
5 Correct 967 ms 178708 KB Output is correct
6 Correct 714 ms 150004 KB Output is correct
7 Correct 863 ms 151720 KB Output is correct
8 Correct 103 ms 66508 KB Output is correct
9 Correct 940 ms 175888 KB Output is correct
10 Correct 967 ms 178832 KB Output is correct
11 Correct 762 ms 149792 KB Output is correct
12 Correct 632 ms 165672 KB Output is correct
13 Correct 670 ms 175980 KB Output is correct
14 Correct 709 ms 178504 KB Output is correct
15 Correct 573 ms 149768 KB Output is correct
16 Correct 663 ms 141952 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 38 ms 63028 KB Output is correct
2 Correct 689 ms 169648 KB Output is correct
3 Correct 561 ms 484464 KB Output is correct
4 Correct 382 ms 324056 KB Output is correct
5 Correct 437 ms 300272 KB Output is correct
6 Correct 143 ms 83828 KB Output is correct
7 Incorrect 262 ms 102224 KB Output isn't correct
8 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 43 ms 63212 KB Output is correct
2 Correct 43 ms 64112 KB Output is correct
3 Incorrect 40 ms 63348 KB Output isn't correct
4 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 43 ms 63212 KB Output is correct
2 Correct 43 ms 64112 KB Output is correct
3 Incorrect 40 ms 63348 KB Output isn't correct
4 Halted 0 ms 0 KB -