/* ID: espr1t TASK: KEYWORDS: CONTEST: CodeIT Round 4 */ #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; FILE *in; FILE *out; struct Point { double x, y; Point(double x_ = 0.0, double y_ = 0.0) : x(x_), y(y_) {} }; struct Square { Point p[4]; Point center; }; const int MAX = 11000; const double EPS = 0.000000001; int n; int ans; Square a[MAX]; vector v[MAX]; bool cross[MAX][MAX]; double fdist(Point p1, Point p2) { return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); } double findArea(Point p1, Point p2, Point p3) { return p1.x * p2.y + p2.x * p3.y + p3.x * p1.y - p1.x * p3.y - p2.x * p1.y - p3.x * p2.y; } bool linesDoCross(Point a1, Point a2, Point b1, Point b2) { double area1, area2; area1 = findArea(a1, a2, b1); area2 = findArea(a1, a2, b2); if (area1 < -EPS && area2 < -EPS) return false; if (area1 > +EPS && area2 > +EPS) return false; area1 = findArea(b1, b2, a1); area2 = findArea(b1, b2, a2); if (area1 < -EPS && area2 < -EPS) return false; if (area1 > +EPS && area2 > +EPS) return false; double mdist = fdist(a1, a2) + fdist(b1, b2); if (fdist(a1, b1) > mdist) return false; if (fdist(a1, b2) > mdist) return false; if (fdist(a2, b1) > mdist) return false; if (fdist(a2, b2) > mdist) return false; return true; } bool doCross(int idx1, int idx2) { for (int i = 0; i < 4; i++) { for (int c = 0; c < 4; c++) { if (linesDoCross(a[idx1].p[i], a[idx1].p[(i + 1) % 4], a[idx2].p[c], a[idx2].p[(c + 1) % 4])) return true; } } return false; } /** * Rotation of a point across a point */ Point rotatePoint(Point p1, Point p2, double angle) { Point ans(p1.x, p1.y); double sinDeg = sin(angle), cosDeg = cos(angle); ans.x += cosDeg * (p2.x - p1.x) - sinDeg * (p2.y - p1.y); ans.y += sinDeg * (p2.x - p1.x) + cosDeg * (p2.y - p1.y); return ans; } void rotate(int idx, double angle) { for (int i = 0; i < 4; i++) { a[idx].p[i] = rotatePoint(a[idx].center, a[idx].p[i], angle); } for (int i = 0; i < (int)v[idx].size(); i++) { bool last = cross[idx][v[idx][i]]; cross[idx][v[idx][i]] = cross[v[idx][i]][idx] = doCross(idx, v[idx][i]); if (last != cross[idx][v[idx][i]]) { if (last) ans--; else ans++; } } } int main(void) { in = stdin; out = stdout; in = fopen("geo.in", "rt"); out = fopen("geo.out", "wt"); fscanf(in, "%d", &n); for (int i = 0; i < n; i++) { fscanf(in, "%lf %lf", &a[i].center.x, &a[i].center.y); a[i].p[0] = Point(a[i].center.x - 8, a[i].center.y - 8); a[i].p[1] = Point(a[i].center.x + 8, a[i].center.y - 8); a[i].p[2] = Point(a[i].center.x + 8, a[i].center.y + 8); a[i].p[3] = Point(a[i].center.x - 8, a[i].center.y + 8); } ans = 0; for (int i = 0; i < n; i++) { for (int c = i + 1; c < n; c++) { double dist = fdist(a[i].center, a[c].center); if (dist < 16.0) { // Always ans++; continue; } if (dist > 22.62742) { // No chance continue; } v[i].push_back(c); v[c].push_back(i); if (doCross(i, c)) { ans++; cross[i][c] = cross[c][i] = true; } else cross[i][c] = cross[c][i] = false; } } int numQueries; fscanf(in, "%d", &numQueries); for (int i = 0; i < numQueries; i++) { int type; fscanf(in, "%d", &type); if (type == 1) { fprintf(out, "%d\n", ans); /* for (int c = 0; c < n; c++) { fprintf(stderr, "Square %d:\n", c); for (int j = 0; j < 4; j++) fprintf(stderr, " >> (%lf, %lf)\n", a[c].p[j].x, a[c].p[j].y); } */ } else { int idx; double rot; fscanf(in, "%d %lf", &idx, &rot); rotate(idx, rot); } } return 0; }