CF475F meta-universe

题意:给你一个无限大矩形中有一些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))。

原文地址:https://www.cnblogs.com/Scx117/p/9082795.html