To give a rectangular pin, a k-knife, each of which is a ray with non-coincident vertices and parallel axes in the cake, ask to cut the pin into several pieces.
Euler's formula: V_E+F=2V-E+F=2V_E+F=2 points_edges+polygons=2 points-edges+polygons=2 points_edges+polygons=2 points_polygons=2.
The original Euler's formula also holds true for such an irregular figure composed of rays...
In this way, the problem is converted from finding the number of polygons to finding the number of points and edges.
Use the Euler formula V_E+F=2V-E+F=2V_E+F=2 to calculate the number of cakes.
First consider the number of points VVV, the four corners of the cake and the end of the ray contributing n+4n+4n+4 vertices. There are n n n intersections between the ray and the four edges, and c c c intersections between the rays, so the number of points is 2n+4+c2n+4+c.Then consider the number of edges. For each ray, assuming that there are c[i]c[i]c[i]c[i] at its intersection, the ray is cut into c[i]+1c[i]+1c[i]+1 segments, so the number of edges for all rays corresponds to 2 c+n2c+n2c+n (since each intersection is used twice).At the same time, because the four edges sum the rays n n n times, there are n+4n+4n+4 edges on the four boundaries, so E=2c+2n+4E=2c+2n+4E=2c+2n+4E=2c+2n+4E=2c+2n+4.So the total number of regions is F=E+2_V=c+2F=E+2-V=c+2F=E+2_V=c+2, because to remove the infinite area outside, the answer is c+1c+1c+1.The problem becomes the number of intersections.This is a classical question. Discuss discretization in four directions using a tree array.Time Complexity O(n log_n)O(nlog{n})O(n log n)
The result is: Number of intersections of rays + 1.
Consider a left-facing ray whose sum of the number of upward rays in the lower left and downward in the upper right is the point at which it contributes; similarly, the number of upward and downward rays in the lower right and upper right is the other half of the total contribution (since only horizontal rays are used at the intersection)Calculate, so don't repeat).
Consider the lower left corner of a left ray. All upward rays in this area count as the answer. So for all left-facing points, we'll ask how many upward points are on the lower left. Put these two types of points together and sort them from smallest to largest in horizontal coordinates, excluding the contribution of points with larger horizontal coordinates than the query points.How can we ensure that the ordinates are less than the query points? We can discretize the ordinates and use BIT to maintain the number of points whose ordinates are less than a certain value. This ensures that the ordinates are less than a given point, and the answer is correct.
Upper left corner of left ray: Contributed by points with small horizontal coordinates and large vertical coordinates, so in order of small to large horizontal coordinates, BIT queries the number of points with larger vertical coordinates than the current point.
Lower right corner of right ray: Contributed by points with large horizontal coordinates and small vertical coordinates, so in order of horizontal coordinates from large to small, BIT queries the number of points less than the current point's vertical coordinates.
Upper right corner of right ray: Contributed by points with large horizontal and large vertical coordinates, so in order of horizontal coordinates from large to small, BIT queries the number of points with larger vertical coordinates than the current point.
Code:
int lowbit(int x) { return x & (-x); } const int M = 212345;// 2e5+5 ll c[M * 2]; void add(int x, ll t, int n) {while (x <= n) {c[x] += t;x += lowbit(x);}} ll query(int x) {ll ret = 0;while (x > 0) {ret += c[x];x -= lowbit(x);}return ret;} struct node {int x, y, type;}; vector<node> cut[5];// 1up 2down 3left 4right vector<int> lSanY; int getId(int x) {return lower_bound(all(lSanY), x) - lSanY.begin() + 1;} vector<node> tmp; bool cmp(node a, node b) {return a.x < b.x;} bool cmp2(node a, node b) {return a.x > b.x;} ll ans; void cal(int hr, int vr) { Mem(c, 0); tmp.clear(); tmp.insert(tmp.end(), all(cut[hr])); tmp.insert(tmp.end(), all(cut[vr])); if (hr == 3)sort(all(tmp), cmp);//Left, horizontal coordinates from small to large else sort(all(tmp), cmp2);//Right, horizontal coordinates sorted from large to small for (auto p:tmp) { if (p.type == 3 || p.type == 4) {//Horizontal Point Query if (vr == 2)ans += query(lSanY.size() + 100) - query(getId(p.y) - 1);//Quadrant 2 or 3 should look for the number of points with large ordinate coordinates else ans += query(getId(p.y));//Quadrant 1 or 4 should look for the number of points with small ordinate } else {// Vertical Point Update add(getId(p.y), 1, lSanY.size() + 100); } } } void init() { int _ = read(); while (_--) { cut[1].clear(), cut[2].clear(), cut[3].clear(), cut[4].clear(); lSanY.clear(); int n = read(), m = read(), k = read(); for (int i = 1; i <= k; ++i) { int x = read(), y = read(); lSanY.emplace_back(y); char op[3]; scanf("%s", op); int type = op[0] == 'U' ? 1 : op[0] == 'D' ? 2 : op[0] == 'L' ? 3 : 4; cut[type].emplace_back((node) {x, y, type}); } sort(all(lSanY)); lSanY.erase(unique(all(lSanY)), lSanY.end()); for (int i = 3; i <= 4; ++i) for (int j = 1; j <= 2; ++j) cal(i, j); write(ans + 1), enter, ans = 0; } }