【HDU】2461 Rectangles

题意:不超过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 }

转载于:https://www.cnblogs.com/DrunBee/archive/2012/09/12/2682214.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值