【題解】[JOISC2020] 美味しい美味しいハンバーグ
阿新 • • 發佈:2021-06-13
\(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; }