题意:不超过20个矩形,100000个询问,求矩形面积并。
线段树复杂度比较靠谱吧。
偷懒用容斥了。由于询问很多,容斥时候会重复用到某几个矩形的面积交,那么可以先预处理出来。
询问的时候枚举子集肯定会TLE的,如果当前面积交为0,就不要再DFS下去了。这样就水过去了。
1 #include<cstdio> 2 #include<algorithm> 3 #define MAXN 20 4 #define MAX(a,b) ((a)>(b)?(a):(b)) 5 #define MIN(a,b) ((a)<(b)?(a):(b)) 6 #define oo 0x7FFFFFFF 7 using namespace std; 8 struct Rec { 9 int x1, y1, x2, y2; 10 }; 11 Rec r[MAXN]; 12 int depth, tot, cnt, pos[MAXN], area[1 << MAXN]; 13 int Get(int x) { 14 int i; 15 Rec tmp; 16 tmp.x1 = tmp.y1 = 0; 17 tmp.x2 = tmp.y2 = oo; 18 for (i = 0; x; x >>= 1, i++) { 19 if (x & 1) { 20 tmp.x1 = MAX(tmp.x1,r[i].x1); 21 tmp.y1 = MAX(tmp.y1,r[i].y1); 22 tmp.x2 = MIN(tmp.x2,r[i].x2); 23 tmp.y2 = MIN(tmp.y2,r[i].y2); 24 } 25 } 26 if (tmp.x2 <= tmp.x1) 27 return 0; 28 if (tmp.y2 <= tmp.y1) 29 return 0; 30 return (tmp.x2 - tmp.x1) * (tmp.y2 - tmp.y1); 31 } 32 void DFS(int index, int now, int state) { 33 if (state && !area[state]) 34 return; 35 if (cnt - index < depth - now) 36 return; 37 if (now == depth) 38 tot += area[state]; 39 else { 40 int i; 41 for (i = index; i < cnt; i++) 42 DFS(i + 1, now + 1, state | (1 << (pos[i] - 1))); 43 } 44 } 45 int Count() { 46 int ans; 47 ans = 0; 48 for (depth = 1; depth <= cnt; depth++) { 49 tot = 0; 50 DFS(0, 0, 0); 51 if (depth & 1) 52 ans += tot; 53 else 54 ans -= tot; 55 } 56 return ans; 57 } 58 int main() { 59 int ca = 1; 60 int n, q; 61 int i, j; 62 while (scanf("%d%d", &n, &q), n) { 63 for (i = 0; i < n; i++) 64 scanf("%d%d%d%d", &r[i].x1, &r[i].y1, &r[i].x2, 65 &r[i].y2); 66 for (i = 1; i < (1 << n); i++) 67 area[i] = Get(i); 68 printf("Case %d:\n", ca++); 69 for (j = 1; j <= q; j++) { 70 scanf("%d", &cnt); 71 for (i = 0; i < cnt; i++) 72 scanf("%d", &pos[i]); 73 sort(pos, pos + cnt); 74 cnt = unique(pos, pos + cnt) - pos; 75 printf("Query %d: %d\n", j, Count()); 76 } 77 putchar('\n'); 78 } 79 return 0; 80 }