题意:给你一个无限大矩形中有一些planet,每次可以选择某一没有planet的行或列分割开矩形(分割开以后要求矩形不为空)。问最后能分割成几个矩形?
标程:
1 #include<bits/stdc++.h> 2 #define P pair<int,int> 3 #define fir first 4 #define sec second 5 using namespace std; 6 const int N=100005; 7 set<P> X,Y; 8 int n,x[N],y[N]; 9 int solve(set<P> &a,set<P> &b)//要加&符号,不然set不能覆盖 10 {//注意a.rbegin()不能作为指针,只能求值如a.rbegin()->fir 11 set<P> ::iterator ta1=a.begin(),ta2=--a.end(),tb1=b.begin(),tb2=--b.end(),nxt,t,ed1,ed2; 12 while (*ta1<=*ta2||*tb1<=*tb2) 13 { 14 assert(!a.empty()); 15 if (ta1!=--a.end()) 16 { 17 nxt=++ta1;--ta1; 18 set<P> aa,bb;//定义在内部,如果在定义在外面clear的时候地址会错误 19 if (ta1->fir+1<nxt->fir){ 20 for (t=a.begin();t!=nxt;) 21 { 22 int u=t->sec;++t;//在没有删除元素之前移动指针,不然会寻不到地址 23 aa.insert(P(x[u],u)),bb.insert(P(y[u],u)),b.erase(P(y[u],u)),a.erase(P(x[u],u));//如果不另储的话,*t移除放在最后 24 } 25 return solve(aa,bb)+solve(a,b); 26 } 27 } 28 if (ta2!=a.begin()) 29 { 30 nxt=--ta2;++ta2; 31 set<P> aa,bb; 32 if (ta2->fir-1>nxt->fir){ 33 for (t=--a.end();t!=nxt;) 34 { 35 int u=t->sec;--t; 36 aa.insert(P(x[u],u)),bb.insert(P(y[u],u)),b.erase(P(y[u],u)),a.erase(P(x[u],u)); 37 } 38 return solve(aa,bb)+solve(a,b); 39 } 40 } 41 if (tb1!=--b.end()) 42 { 43 nxt=++tb1;--tb1; 44 set<P> aa,bb; 45 if (tb1->fir+1<nxt->fir){ 46 for (t=b.begin();t!=nxt;) 47 { 48 int u=t->sec;++t; 49 aa.insert(P(x[u],u)),bb.insert(P(y[u],u)),b.erase(P(y[u],u)),a.erase(P(x[u],u)); 50 } 51 return solve(aa,bb)+solve(a,b); 52 } 53 } 54 if (tb2!=b.begin()) 55 { 56 nxt=--tb2;++tb2; 57 set<P> aa,bb; 58 if (tb2->fir-1>nxt->fir){ 59 for (t=--b.end();t!=nxt;) 60 { 61 int u=t->sec;--t; 62 aa.insert(P(x[u],u)),bb.insert(P(y[u],u)),b.erase(P(y[u],u)),a.erase(P(x[u],u)); 63 } 64 return solve(aa,bb)+solve(a,b); 65 } 66 } 67 ed1=--a.end(),ed2=--b.end(); 68 if (ta1==ed1&&tb1==ed2) break; 69 if (ta1!=ed1) ++ta1,--ta2; 70 if (tb1!=ed2) ++tb1,--tb2; 71 } 72 return 1; 73 } 74 int main() 75 { 76 scanf("%d",&n); 77 for (int i=1;i<=n;i++) 78 { 79 scanf("%d%d",&x[i],&y[i]); 80 X.insert(P(x[i],i));Y.insert(P(y[i],i)); 81 } 82 printf("%d ",solve(X,Y)); 83 return 0; 84 }
易错点:set操作注意一下。
题解:set+启发式分割
将所有的planet存入行set和列set。
每次从行和列的两边(启发式)往中间找空行/列,然后剖开,递归求解子问题。
时间复杂度O((n+m)log(n+m))。