【题解】[JOISC2020] 美味しい美味しいハンバーグ
\(K\) 非常小,先找特殊性质。
首先 \(K=1\) 的时候直接求交集即可。
对于 \(K=2\) ,先考虑固定第一个点。我们令左的右边界为 \(x\) ,那么第一个点的横坐标为 \(x\) 一定最优。因为如果横坐标 \(>x\) ,一定会漏掉某个矩形,如果 \(<x\) ,而不存在右端点 \(<x\) 的,所以选则 \(x\) 一定最优。
同理我们找到最右的左边界,最上的下边界和最下的上边界。那么一定选择这些边界上的点最优。
对于 \(K\le 3\) 的情况,我们只有三个点却要覆盖四个边界,那么只能选择边界的交点。而交点只有 \(4\) 个,所以我们直接暴搜即可。时间复杂度 \(\mathcal{O}(4^KN)\) 。
对于 \(K=4\) 还有一种情况是四个边界每个边界上恰好一个点。
那么对于每个矩形。一定与某些边界有交集,且不可能与四个同时
如果至少与四个边界中的三个有交集,那么一定包含一条边界,这类矩形可以忽略。
如果与四个边界中的一个有交集,那么这个边界上的点一定在交集内。
否则会与四个边界中的两个有交集,我们令两个交集为 \([l_1,r_1]\) 和 \([l_2,r_2]\) ,那么两个中至少选择一个,经典 2-SAT 问题,直接建图跑即可。
时间复杂度 \(\mathcal{ O}(4^KN+N\log N)\) 。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define N 200005
#define M 2000005
using namespace std;
const int inf = 0x7fffffff;
int n,k,v[N],idx;
struct node{int l,r,u,d;}a[N];
struct pt{
int x,y;
pt(int X=0,int Y=0){x=X,y=Y;}
}sta[5],lim[4];
bool ck(node x,pt y){return x.l<=y.x&&y.x<=x.r&&x.d<=y.y&&y.y<=x.u;}
pt ad(pt x,pt y){return pt(max(x.x,y.x),min(x.y,y.y));}
struct seg{
int l,r,op;
seg(int L=0,int R=0,int O=0){l=L,r=R,op=O;}
};
vector<seg>c[4];
int h[M],tot,f[N];
struct edge{int to,nxt;}e[M<<1];
void add(int x,int y){e[++tot].nxt=h[x];h[x]=tot;e[tot].to=y;}
int rev(int x){if(x>n*2)return x-n*2;return x+n*2;}
void calc(int l,int r,int d,int u,node x){
int sum=0;pt p,q;int opx=~0,opy=~0;
if(x.l<=l&&l<=x.r)q=pt(x.d,x.u),opy=0,swap(p,q),swap(opx,opy),sum++;
if(x.l<=r&&r<=x.r)q=pt(x.d,x.u),opy=1,swap(p,q),swap(opx,opy),sum++;
if(x.d<=d&&d<=x.u)q=pt(x.l,x.r),opy=2,swap(p,q),swap(opx,opy),sum++;
if(x.d<=u&&u<=x.u)q=pt(x.l,x.r),opy=3,swap(p,q),swap(opx,opy),sum++;
if(sum>=3)return;
if(sum==1)lim[opx]=ad(lim[opx],p);
if(sum==2){
c[opx].push_back(seg(p.x,p.y,++idx));
c[opy].push_back(seg(q.x,q.y,++idx));
add(rev(idx-1),idx);add(rev(idx),idx-1);
}
}
bool cmp1(seg x,seg y){return x.r<y.r;}
bool cmp2(seg x,seg y){return x.l<y.l;}
int dfn[M],st[M],top,cnt,cc,low[M],mat[M],vis[M];
void tar(int x){
dfn[x]=low[x]=++cc;vis[st[++top]=x]=1;
for(int i=h[x];i;i=e[i].nxt){
if(!dfn[e[i].to])tar(e[i].to),low[x]=min(low[x],low[e[i].to]);
else if(vis[e[i].to])low[x]=min(low[x],dfn[e[i].to]);
}
if(dfn[x]==low[x]){
++cnt;
while(true){
int y=st[top--];
vis[y]=0;mat[y]=cnt;
if(x==y)return;
}
}
}
void solve(){
int l=~0,r=inf,u=inf,d=~0;
rep(i,1,n)l=max(l,a[i].l),r=min(r,a[i].r),u=min(u,a[i].u),d=max(d,a[i].d);
rep(i,0,3)lim[i]=pt(0,inf);rep(i,1,n)calc(r,l,u,d,a[i]);
idx+=2*n;
rep(op,0,3){
sort(c[op].begin(),c[op].end(),cmp1);
int sz=c[op].size();
for(int i=0;i<sz;i++){
if(c[op][i].r<lim[op].x||c[op][i].l>lim[op].y)
add(c[op][i].op,rev(c[op][i].op));
f[i]=++idx;add(f[i],rev(c[op][i].op));
if(i>0)add(f[i],f[i-1]);
int l=0,r=i-1,ed=~0;
while(l<=r){
int mid=(l+r)>>1;
if(c[op][mid].r<c[op][i].l)ed=mid,l=mid+1;
else r=mid-1;
}
if(~ed)add(c[op][i].op,f[ed]);
}
sort(c[op].begin(),c[op].end(),cmp2);
for(int i=sz-1;i>=0;i--){
f[i]=++idx;add(f[i],rev(c[op][i].op));
if(i<sz-1)add(f[i],f[i+1]);
int l=i+1,r=sz-1,ed=~0;
while(l<=r){
int mid=(l+r)>>1;
if(c[op][mid].l>c[op][i].r)ed=mid,r=mid-1;
else l=mid+1;
}
if(~ed)add(c[op][i].op,f[ed]);
}
}
memset(v,0,sizeof(v));
rep(i,1,idx)if(!dfn[i])tar(i);
rep(op,0,3){
for(int i=0;i<(int)c[op].size();i++){
int x=c[op][i].op,y=rev(x);
if(mat[x]<mat[y])lim[op]=ad(lim[op],pt(c[op][i].l,c[op][i].r));
}
}
printf("%d %d\n",r,lim[0].x);
printf("%d %d\n",l,lim[1].x);
printf("%d %d\n",lim[2].x,u);
printf("%d %d\n",lim[3].x,d);
}
bool dfs(int x){
vector<int>is;
int l=~0,r=inf,u=inf,d=~0;
rep(i,1,n)if(!v[i])
l=max(l,a[i].l),r=min(r,a[i].r),u=min(u,a[i].u),d=max(d,a[i].d);
if(-1==l){
if(x==k+1){
rep(i,1,k)printf("%d %d\n",sta[i].x,sta[i].y);
return true;
}
sta[x]=pt(0,0);
}
if(x>k)return false;
// type = 1 (l,u)
pt cur=pt(l,u);sta[x]=cur;
rep(i,1,n)if(!v[i]&&ck(a[i],cur))is.push_back(i),v[i]=1;
if(dfs(x+1))return true;
for(int i=0;i<(int)is.size();i++)v[is[i]]=0;is.clear();
// type = 2 (l,d)
cur=pt(l,d);sta[x]=cur;
rep(i,1,n)if(!v[i]&&ck(a[i],cur))is.push_back(i),v[i]=1;
if(dfs(x+1))return true;
for(int i=0;i<(int)is.size();i++)v[is[i]]=0;is.clear();
// type = 3 (r,u)
cur=pt(r,u);sta[x]=cur;
rep(i,1,n)if(!v[i]&&ck(a[i],cur))is.push_back(i),v[i]=1;
if(dfs(x+1))return true;
for(int i=0;i<(int)is.size();i++)v[is[i]]=0;is.clear();
// type = 4 (r,d)
cur=pt(r,d);sta[x]=cur;
rep(i,1,n)if(!v[i]&&ck(a[i],cur))is.push_back(i),v[i]=1;
if(dfs(x+1))return true;
for(int i=0;i<(int)is.size();i++)v[is[i]]=0;is.clear();
return false;
}
int main(){
//freopen("08-14.in","r",stdin);
freopen("INPUT","r",stdin);
scanf("%d%d",&n,&k);
rep(i,1,n)scanf("%d%d%d%d",&a[i].l,&a[i].d,&a[i].r,&a[i].u);
if(!dfs(1))solve();
return 0;
}