[loj3272]汉堡肉

当$k\le 3$,这是一个经典的问题

设所有矩形左下角横纵坐标的最大值为$(x_{1},y_{1})$,右上角横纵坐标的最小值为$(x_{2},y_{2})$,那么必然存在一组合法解满足其中一点为$(x_{1}/x_{2},y_{1}/y_{2})$,不断递归即可,时间复杂度为$o(4^{k}n)$

当$k=4$,我们可以在四条边界线上各放一点来完成

如果一个矩形完全覆盖了一条边(即覆盖了3或4条边,注意覆盖和完全覆盖不同),那么一定含有一个点,因此这类矩形的限制可以删掉

对于剩下的矩形,其覆盖了1或2条边:对于覆盖1条边的,即每一个点有一个范围的限制;对于覆盖2条边的点,分类讨论:

1.相邻的两条边,由于都是前缀/后缀,利用单调性维护

2.相对的两条边,用线段树区间修改,维护出每一个点所对应的合法区间(求交)

根据这个,枚举其中的一个点(离散),则其相邻的一条边上必然有一点选择其所限制的位置,再通过这两个点得到另外两点的限制,最后判断这两个点的限制能否满足(即这两个区间不为空且最相近时能否合法)

时间复杂度为$o(n\log_{2}n+4^{k}n)$,即可通过

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 200005
  4 #define oo 0x3f3f3f3f
  5 #define pii pair<int,int>
  6 #define mp make_pair
  7 #define fi first
  8 #define se second
  9 #define L (k<<1)
 10 #define R (L+1)
 11 #define mid (l+r>>1)
 12 struct ji{
 13     int x1,y1,x2,y2;
 14 }a[N];
 15 vector<int>vx,vy,vv;
 16 vector<pii >ans;
 17 int n,m,vis[N],lim1[N],lim2[N],lim3[N],lim4[N];
 18 pii f[2][N<<2];
 19 void update(pii o,int k){
 20     ans.push_back(o);
 21     for(int i=1;i<=n;i++)
 22         if ((!vis[i])&&(a[i].x1<=o.fi)&&(o.fi<=a[i].x2)&&(a[i].y1<=o.se)&&(o.se<=a[i].y2))vis[i]=k;
 23 }
 24 void clear(int k){
 25     ans.pop_back();
 26     for(int i=1;i<=n;i++)
 27         if (vis[i]==k)vis[i]=0;
 28 }
 29 bool dfs(int k){
 30     if (k>m){
 31         for(int i=1;i<=n;i++)
 32             if (!vis[i])return 0;
 33         return 1;
 34     }
 35     ji o=ji{oo,oo,0,0};
 36     for(int i=1;i<=n;i++)
 37         if (!vis[i]){
 38             o.x1=min(o.x1,a[i].x2);
 39             o.y1=min(o.y1,a[i].y2);
 40             o.x2=max(o.x2,a[i].x1);
 41             o.y2=max(o.y2,a[i].y1);
 42         }
 43     update(mp(o.x1,o.y1),k);
 44     if (dfs(k+1))return 1;
 45     clear(k);
 46     update(mp(o.x1,o.y2),k);
 47     if (dfs(k+1))return 1;
 48     clear(k);
 49     update(mp(o.x2,o.y1),k);
 50     if (dfs(k+1))return 1;
 51     clear(k);
 52     update(mp(o.x2,o.y2),k);
 53     if (dfs(k+1))return 1;
 54     clear(k);
 55     return 0;
 56 }
 57 void org(vector<int>&v,int l,int r){
 58     sort(v.begin(),v.end());
 59     vv.clear();
 60     for(int i=0;i<v.size();i++)
 61         if ((l<=v[i])&&(v[i]<=r)&&((!vv.size())||(v[i]!=vv[vv.size()-1])))vv.push_back(v[i]);
 62     v=vv;
 63 }
 64 pii merge(pii x,pii y){
 65     return mp(max(x.fi,y.fi),min(x.se,y.se));
 66 }
 67 void build(int p,int k,int l,int r,int x){
 68     f[p][k]=mp(1,x);
 69     if (l==r)return;
 70     build(p,L,l,mid,x);
 71     build(p,R,mid+1,r,x);
 72 }
 73 void update(int p,int k,int l,int r,int x,int y,pii z){
 74     if ((l>y)||(x>r))return;
 75     if ((x<=l)&&(r<=y)){
 76         f[p][k]=merge(f[p][k],z);
 77         return;
 78     }
 79     update(p,L,l,mid,x,y,z);
 80     update(p,R,mid+1,r,x,y,z);
 81 }
 82 pii query(int p,int k,int l,int r,int x){
 83     if (l==r)return f[p][k];
 84     if (x<=mid)return merge(f[p][k],query(p,L,l,mid,x));
 85     return merge(f[p][k],query(p,R,mid+1,r,x));
 86 }
 87 int main(){
 88     scanf("%d%d",&n,&m);
 89     for(int i=1;i<=n;i++)scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
 90     if (dfs(1)){
 91         for(int i=0;i<m;i++)printf("%d %d\n",ans[i].fi,ans[i].se);
 92         return 0;
 93     }
 94     ji o=ji{oo,oo,0,0};
 95     for(int i=1;i<=n;i++){
 96         o.x1=min(o.x1,a[i].x2);
 97         o.y1=min(o.y1,a[i].y2);
 98         o.x2=max(o.x2,a[i].x1);
 99         o.y2=max(o.y2,a[i].y1);
100     }
101     for(int i=1;i<=n;i++){
102         vx.push_back(a[i].x1);
103         vy.push_back(a[i].y1);
104         vx.push_back(a[i].x2);
105         vy.push_back(a[i].y2);
106     }
107     org(vx,o.x1,o.x2);
108     org(vy,o.y1,o.y2);
109     int nx=vx.size(),ny=vy.size();
110     build(0,1,1,ny,nx);
111     build(1,1,1,nx,ny);
112     int l1=0,l2=0;
113     for(int i=1;i<=n;i++){
114         a[i].x1=lower_bound(vx.begin(),vx.end(),a[i].x1)-vx.begin()+1;
115         a[i].x1=min(a[i].x1,nx);
116         a[i].y1=lower_bound(vy.begin(),vy.end(),a[i].y1)-vy.begin()+1;
117         a[i].y1=min(a[i].y1,ny);
118         a[i].x2=lower_bound(vx.begin(),vx.end(),a[i].x2)-vx.begin()+1;
119         a[i].x2=min(a[i].x2,nx);
120         a[i].y2=lower_bound(vy.begin(),vy.end(),a[i].y2)-vy.begin()+1;
121         a[i].y2=min(a[i].y2,ny);
122     }
123     for(int i=1;i<=ny;i++)lim1[i]=lim2[i]=nx;
124     for(int i=1;i<=nx;i++)lim3[i]=ny;
125     for(int i=1;i<=nx;i++)lim4[i]=1;
126     for(int i=1;i<=n;i++){
127         if ((a[i].x1==1)&&(a[i].x2==nx)){
128             if ((a[i].y1==1)||(a[i].y2==ny))continue;
129             update(0,1,1,ny,1,a[i].y1-1,mp(a[i].y1,a[i].y2));
130             update(0,1,1,ny,a[i].y2+1,ny,mp(a[i].y1,a[i].y2));
131             continue;
132         }
133         if ((a[i].y1==1)&&(a[i].y2==ny)){
134             if ((a[i].x1==1)||(a[i].x2==nx))continue;
135             update(1,1,1,nx,1,a[i].x1-1,mp(a[i].x1,a[i].x2));
136             update(1,1,1,nx,a[i].x2+1,nx,mp(a[i].x1,a[i].x2));
137             continue;
138         }
139         if (a[i].x1==1){
140             if (a[i].y1==1)lim1[a[i].y2+1]=min(lim1[a[i].y2+1],a[i].x2);
141             if (a[i].y2==ny)lim2[a[i].y1-1]=min(lim2[a[i].y1-1],a[i].x2);
142             if ((a[i].y1!=1)&&(a[i].y2!=ny)){
143                 update(0,1,1,ny,1,a[i].y1-1,mp(nx,1));
144                 update(0,1,1,ny,a[i].y2+1,ny,mp(nx,1));
145             }
146             continue;
147         }
148         if (a[i].x2==nx){
149             if (a[i].y1==1)lim3[a[i].x1-1]=min(lim3[a[i].x1-1],a[i].y2);
150             if (a[i].y2==ny)lim4[a[i].x1-1]=max(lim4[a[i].x1-1],a[i].y1);
151             if ((a[i].y1!=1)&&(a[i].y2!=ny))update(0,1,1,ny,1,ny,mp(a[i].y1,a[i].y2));
152             continue;
153         }
154         if (a[i].y1==1){
155             l1=max(l1,a[i].x1);
156             lim1[1]=min(lim1[1],a[i].x2);
157         }
158         if (a[i].y1==ny){
159             l2=max(l2,a[i].x1);
160             lim2[ny]=min(lim2[ny],a[i].x2);
161         }
162     }
163     for(int i=2;i<=ny;i++)lim1[i]=min(lim1[i],lim1[i-1]);
164     for(int i=ny-1;i;i--)lim2[i]=min(lim2[i],lim2[i+1]);
165     for(int i=nx-1;i;i--)lim3[i]=min(lim3[i],lim3[i+1]);
166     for(int i=nx-1;i;i--)lim4[i]=max(lim4[i],lim4[i+1]);
167     for(int i=1;i<=ny;i++){
168         if (!lim1[i])continue;
169         pii o1=query(0,1,1,ny,i),o2=query(1,1,1,nx,lim1[i]);
170         o1.se=min(o1.se,lim3[lim1[i]]);
171         o2.se=min(o2.se,lim2[i]);
172         if ((o1.fi>o1.se)||(o2.fi>o2.se))continue;
173         if (o1.se>=lim4[o2.se]){
174             printf("%d %d\n",vx[0],vy[i-1]);
175             printf("%d %d\n",vx[lim1[i]-1],vy[0]);
176             printf("%d %d\n",vx[nx-1],vy[o1.se-1]);
177             printf("%d %d\n",vx[o2.se-1],vy[ny-1]);
178             return 0;
179         }
180     }
181     for(int i=1;i<=ny;i++){
182         if (!lim2[i])continue;
183         pii o1=query(0,1,1,ny,i),o2=query(1,1,1,nx,lim2[i]);
184         o1.fi=max(o1.fi,lim4[lim2[i]]);
185         o2.se=min(o2.se,lim1[i]);
186         if ((o1.fi>o1.se)||(o2.fi>o2.se))continue;
187         if (o1.fi<=lim3[o2.se]){
188             printf("%d %d\n",vx[0],vy[i-1]);
189             printf("%d %d\n",vx[lim2[i]-1],vy[ny-1]);
190             printf("%d %d\n",vx[nx-1],vy[o1.fi-1]);
191             printf("%d %d\n",vx[o2.se-1],vy[0]);
192             return 0;
193         }
194     }
195     return 0;
196 }
View Code

 

posted @ 2020-10-24 15:20  PYWBKTDA  阅读(154)  评论(0编辑  收藏  举报