题目链接:点击打开链接
一个详细的题解:点击打开链接
题目大意是给出若干个矩形(n <= 20) 然后m个询问(m <= 100000)
每个询问会给出一些矩形的编号,问这些矩形的面积并有多大
谈到矩形并,也许第一反应都是线段树
但是此题有一个特点,就是n非常小,m却非常大
用线段树很有可能会不行
于是换个思路,n很小,我们可以把所有的可能组合情况都考虑到,然后呢预处理出来,这样询问时就是O(1)的查询了
但是1<<20显然是远大于100000的
也就是说我们没必要把所有情况都考虑到。
只需要考虑这m个询问中的情况就可以了
于是我们先把询问中情况都读进来,用二进制存起来。
然后就是DFS,根据容斥原理
一个矩形的面积-二个矩形相交的面积+三个矩形相交的面积。。。。。。就这样
所以DFS中可以有两种分支,一种是拿这个矩形,另一种是不拿
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <vector>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
const int inf = 1e8;
const double eps = 1e-8;
const double pi = acos(-1.0);
template <class T>
inline bool rd(T &ret) {
char c; int sgn;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
ret*=sgn;
return 1;
}
template <class T>
inline void pt(T x) {
if (x <0) { putchar('-');x = -x; }
if(x>9) pt(x/10);
putchar(x%10+'0');
}
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int n, m;
struct node{
int x1, x2, y1, y2;
int area(){return abs(x1-x2)*abs(y1-y2);}
}a[30];
int ask[100005];
int st[1<<21];
void dfs(int xa, int ya, int xb, int yb, int deep, int flag, int sta){
if(xa >= xb || ya >= yb)return;
if(deep == n)
{
if(sta){
for(int i = 1; i <= m; i++)
if((ask[i]|sta) == ask[i])
st[ask[i]] += flag*(xb-xa)*(yb-ya);
}
return ;
}
dfs(xa, ya, xb, yb, deep+1, flag, sta);
dfs(max(xa, a[deep+1].x1), max(ya, a[deep+1].y1), min(xb, a[deep+1].x2), min(yb, a[deep+1].y2), deep+1, -flag, sta|(1<<deep));
}
int main(){
int Cas = 1;
while(cin>>n>>m, n+m){
printf("Case %d:\n", Cas++);
for(int i = 1; i <= n; i++){
rd(a[i].x1); rd(a[i].y1); rd(a[i].x2); rd(a[i].y2);
}
for(int i = 1, siz, num; i <= m; i++){
ask[i] = 0;
rd(siz);
while(siz-->0){rd(num); ask[i]|=1<<(num-1);}
}
memset(st, 0, sizeof st);
dfs(0,0,inf,inf, 0,-1,0);
for(int i = 1; i <= m; i++)
printf("Query %d: %d\n", i, st[ask[i]]);
puts("");
}
return 0;
}