HDU-2461 Rectangles 容斥
阿新 • • 發佈:2018-11-03
題意:給出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; }