HDU-2461 Rectangles 容斥

题意:给出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;
}

猜你喜欢

转载自blog.csdn.net/qq_40679299/article/details/83045527