#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()) {
| ~~^~~~~~~~~~~~~~~~~
rainbow.cpp: In function 'int main()':
rainbow.cpp:297:22: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
297 | init(6, 4, 3, 3, 9, "NWESSWEWS");
| ^~~~~~~~~~~
/usr/bin/ld: /tmp/ccFuWKmQ.o: in function `main':
grader.cpp:(.text.startup+0x0): multiple definition of `main'; /tmp/ccyBAwyO.o:rainbow.cpp:(.text.startup+0x0): first defined here
collect2: error: ld returned 1 exit status