POJ 3695 Rectangles (矩形并 状压+容斥定理 好题)


Rectangles
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<=RN), 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

2008 Asia Hefei Regional Contest Online by USTC

题目链接: 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");
    }
}


你可能感兴趣的:(poj,容斥)