Loading

【题解】[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;
}
posted @ 2021-06-13 19:58  7KByte  阅读(77)  评论(0编辑  收藏  举报