Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 3730 | Accepted: 1082 |
Description
You are developing a software for painting rectangles on the screen. The software supports drawing several rectangles and filling some of them with a color different from the color of the background. You are to implement an important function. The function answer such queries as what is the colored area if a subset of rectangles on the screen are filled.
Input
The input consists of multiple test cases. Each test case starts with a line containing two integers N(1 ≤ N ≤ 20) and M(1 ≤ M ≤ 100000), indicating the number of rectangles on the screen and the number of queries, respectively.
The i-th line of the following N lines contains four integers X1,Y1,X2,Y2 (0 ≤ X1 < X2 ≤ 1000, 0 ≤ Y1 < Y2 ≤ 1000), which indicate that the lower-left and upper-right coordinates of the i-th rectangle are (X1, Y1) and (X2, Y2). Rectangles are numbered from 1 to N.
The last M lines of each test case describe M queries. Each query starts with a integer R(1<=R ≤ N), which is the number of rectangles the query is supposed to fill. The following list of R integers in the same line gives the rectangles the query is supposed to fill, each integer of which will be between 1 and N, inclusive.
The last test case is followed by a line containing two zeros.
Output
For each test case, print a line containing the test case number( beginning with 1).
For each query in the input, print a line containing the query number (beginning with 1) followed by the corresponding answer for the query. Print a blank line after the output for each test case.
Sample Input
2 2 0 0 2 2 1 1 3 3 1 1 2 1 2 2 1 0 1 1 2 2 1 3 2 2 1 2 0 0
Sample Output
Case 1: Query 1: 4 Query 2: 7 Case 2: Query 1: 2
Source
题目链接: http://poj.org/problem?id=3695
题目大意:给出n个矩形,用它们的对顶点表示,m个查询,每个查询给出r个数,求这r个矩形并在一起的图形面积
题目分析:本题有个特点就是n很小但是m很大,因此我们可以把询问的状态用二进制压缩,然后直接计算出这些询问的状态,O(1)查询即可,计算每种状态时,在DFS中容斥,如三个矩形两两相交,设面积为A,B,C则A∪B∪C = A + B + C - A∩B - A∩C - B∩C + A∩B∩C,交的时候可以通过对顶角的坐标来计算相交部分的面积,至于容斥时的符号,在DFS里用一个参数sgin表示,每一次交完变一下号即可,对于每个矩形(包括并出来的小矩形)分别搜索选和不选两种状态
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int const INF = 0x3fffffff;
int const MAX = 1 << 21;
int q[MAX], ans[MAX];
int n, m;
struct R
{
int x1, y1;
int x2, y2;
}r[25];
void DFS(int x1, int y1, int x2, int y2, int pos, int sgin, int sta)
{
if(x1 >= x2 || y1 >= y2)
return;
if(pos == n + 1)
{
if(sta)
for(int i = 1; i <= m; i++)
if((q[i] & sta) == sta)
ans[q[i]] += sgin * (x2 - x1) * (y2 - y1);
return;
}
int xx1 = max(x1, r[pos + 1].x1);
int yy1 = max(y1, r[pos + 1].y1);
int xx2 = min(x2, r[pos + 1].x2);
int yy2 = min(y2, r[pos + 1].y2);
DFS(x1, y1, x2, y2, pos + 1, sgin, sta);
DFS(xx1, yy1, xx2, yy2, pos + 1, -sgin, sta | (1 << pos));
return;
}
int main()
{
int ca = 1;
while(scanf("%d %d", &n, &m) != EOF && (n + m))
{
memset(q, 0, sizeof(q));
memset(ans, 0, sizeof(ans));
printf("Case %d:\n", ca++);
for(int i = 1; i <= n; i++)
scanf("%d %d %d %d", &r[i].x1, &r[i].y1, &r[i].x2, &r[i].y2);
for(int i = 1; i <= m; i++)
{
int num;
scanf("%d", &num);
while(num --)
{
int tmp;
scanf("%d", &tmp);
q[i] |= (1 << (tmp - 1));
}
}
DFS(0, 0, INF, INF, 0, -1, 0);
for(int i = 1; i <= m; i++)
printf("Query %d: %d\n", i, ans[q[i]]);
printf("\n");
}
}