题目链接:http://poj.org/problem?id=3695
题意:给你n个矩形,m个询问,每个询问是问几个矩形的面积并
由于n很小,所以把询问存下来,把所有的询问的情况状压记录,O(1)输出
记录的时候对于相交的矩形的面积可以用容斥原理求解,20个矩形的话dfs处理就好了
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define ll long long
using namespace std;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
struct node{
int x1, x2, y1, y2;
}pos[21];
int n, m, ask[maxn], ans[1 << 21];
void dfs(int x1, int y1, int x2, int y2, int deep, int sign, int sta){
if(x1 >= x2 || y1 >= y2) return;
if(deep == n){
if(sta){
for(int i = 0; i < m; i++) {
if((ask[i] | sta) == ask[i]){
ans[ask[i]] += sign * (x2 - x1) * (y2 - y1);
}
}
}
return;
}
int xx1 = max(x1, pos[deep].x1);
int xx2 = min(x2, pos[deep].x2);
int yy1 = max(y1, pos[deep].y1);
int yy2 = min(y2, pos[deep].y2);
dfs(x1, y1, x2, y2, deep + 1, sign, sta);
dfs(xx1, yy1, xx2, yy2, deep + 1, -sign, sta | (1 << deep));
}
int main() {
int t = 1;
while(scanf("%d%d", &n, &m) && n && m){
for(int i = 0; i < n; i++) {
scanf("%d%d%d%d",&pos[i].x1, &pos[i].y1, &pos[i].x2, &pos[i].y2);
}
for(int i = 0; i < m; i++)ask[i] = 0;
for(int i = 0; i < (1 << 21); i++) ans[i] = 0;
for(int i = 0; i < m; i++) {
int q, x;
scanf("%d", &q);
while(q--) {
scanf("%d", &x);
ask[i] |= (1 << (x - 1));
}
}
dfs(0, 0, INF, INF, 0, -1, 0);
printf("Case %d:\n", t++);
for(int i = 0; i < m; i++) {
printf("Query %d: %d\n", i + 1, ans[ask[i]]);
}
printf("\n");
}
return 0;
}