题意:给出n个矩形的左下角和右上角坐标,要求进行m次操作,每次对t个矩形进行涂色(给出这t个矩形的序号),要求计算出每次涂色时需要涂色的面积。(涂色可以覆盖,即每次操作不受前面任何操作的影响)。
分析:因为n很小,所以明显用容斥就可以解决。奇加偶减,算相交面积。
一直习惯用位写容斥,但这个题n是20,循环过多,TLE了,然后看vj上有人先用位打了个表,也挺快的,不过没看懂,还是换过来用dfs写吧。
#include<bits/stdc++.h>
using namespace std;
struct rect{
int x1,y1,x2,y2;
rect(int x1,int y1,int x2,int y2):x1(x1),y1(y1),x2(x2),y2(y2){}
rect(){}
int area(){
if(x1>=x2||y1>=y2){
return 0;
}
return (x2-x1)*(y2-y1);
}
rect cross(const rect& r){
rect t;
t.x1=max(x1,r.x1);
t.y1=max(y1,r.y1);
t.x2=min(x2,r.x2);
t.y2=min(y2,r.y2);
return t;
}
}r[25];
int cnt,ans;
vector<int> v;
void dfs(int i,rect tmp,int num){
tmp=tmp.cross(r[v[i]]);
int area=tmp.area();
if(area==0) return ;
if(num%2) ans+=area;
else ans-=area;
for(int j=i+1;j<cnt;j++){
dfs(j,tmp,num+1);
}
}
int main(){
int n,m;
int cs=1;
while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&r[i].x1,&r[i].y1,&r[i].x2,&r[i].y2);
}
printf("Case %d:\n",cs++);
int css=1;
while(m--){
scanf("%d",&cnt);
v.clear();
ans=0;
for(int i=0;i<cnt;i++){
int a;scanf("%d",&a);
v.push_back(a);
}
for(int i=0;i<cnt;i++){
dfs(i,r[v[i]],1);
}
printf("Query %d: %d\n",css++,ans);
}
puts("");
}
return 0;
}