题目
求出最右的左边界,最左的右边界,最上的下边界,最下的上边界。
K
≤
3
K\leq 3
K≤3时必有一个牙签插在两个边界的交点。
那么
O
(
4
)
O(4)
O(4)枚举插在哪个交点爆搜,深度是
K
K
K,时间复杂度
O
(
n
4
K
)
O(n4^K)
O(n4K)
K
=
4
K = 4
K=4的时候我们必有一种方案可以在每个最边界上都放一个点。
所以和3个边界以上有交的就一定会被插到,
我们只需要考虑和两个一下边界有交的矩形,
考虑
2
−
s
a
t
2-sat
2−sat。
那么和两个边界有交的就变成了两种选择(选择在哪个边上被插),在一条边界上,两个矩形无交,那么这两个矩形就不能同时在这条边上被插,前后缀优化建边即可。
和一个边界有交的,就是有一种选择一定不会被选,那么从那种选择往另一种选择连边即可。
A C C o d e \mathcal AC \ Code AC Code
#include<bits/stdc++.h>
#define maxn 400005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;
int n,K;
int L[maxn][2],R[maxn][2],sx[maxn<<1],sy[maxn<<1];
int ans[4][2];
namespace Solver1{
int usd[maxn] , flg = 0;
void dfs(int u){
int mx[2] = {0,0} , mn[2] = {0x3f3f3f3f,0x3f3f3f3f};
rep(i,1,n) if(!usd[i]) rep(j,0,1)
mn[j] = min(mn[j] , R[i][j]) ,
mx[j] = max(mx[j] , L[i][j]);
if(!mx[0]) return (void)(flg = 1);
if(u == K) return;
ans[u][0] = mn[0] , ans[u][1] = mn[1];
rep(i,1,n) if(L[i][0] <= ans[u][0] && L[i][1] <= ans[u][1] && ans[u][0] <= R[i][0] && ans[u][1] <= R[i][1])
usd[i]++;
dfs(u+1);
if(flg) return;
rep(i,1,n) if(L[i][0] <= ans[u][0] && L[i][1] <= ans[u][1] && ans[u][0] <= R[i][0] && ans[u][1] <= R[i][1])
usd[i]--;
ans[u][0] = mx[0] , ans[u][1] = mx[1];
rep(i,1,n) if(L[i][0] <= ans[u][0] && L[i][1] <= ans[u][1] && ans[u][0] <= R[i][0] && ans[u][1] <= R[i][1])
usd[i]++;
dfs(u+1);
if(flg) return;
rep(i,1,n) if(L[i][0] <= ans[u][0] && L[i][1] <= ans[u][1] && ans[u][0] <= R[i][0] && ans[u][1] <= R[i][1])
usd[i]--;
ans[u][0] = mx[0] , ans[u][1] = mn[1];
rep(i,1,n) if(L[i][0] <= ans[u][0] && L[i][1] <= ans[u][1] && ans[u][0] <= R[i][0] && ans[u][1] <= R[i][1])
usd[i]++;
dfs(u+1);
if(flg) return;
rep(i,1,n) if(L[i][0] <= ans[u][0] && L[i][1] <= ans[u][1] && ans[u][0] <= R[i][0] && ans[u][1] <= R[i][1])
usd[i]--;
ans[u][0] = mn[0] , ans[u][1] = mx[1];
rep(i,1,n) if(L[i][0] <= ans[u][0] && L[i][1] <= ans[u][1] && ans[u][0] <= R[i][0] && ans[u][1] <= R[i][1])
usd[i]++;
dfs(u+1);
if(flg) return;
rep(i,1,n) if(L[i][0] <= ans[u][0] && L[i][1] <= ans[u][1] && ans[u][0] <= R[i][0] && ans[u][1] <= R[i][1])
usd[i]--;
}
void Solve(){
dfs(0);
if(flg){
for(int i=0;i<K;i++)
printf("%d %d\n",sx[ans[i][0]] , sy[ans[i][1]]);
exit(0);
}
}
}
namespace Solver2{
int p[maxn][2] , tot = 1;
#define pii pair<int,int>
#define mp make_pair
vector<int>in[4][maxn],ot[4][maxn],cs[maxn];
#define maxp maxn * 10
#define maxm maxp * 2
int info[maxp],Prev[maxm],to[maxm],cnt_e;
void Node(int u,int v){
if(u && v)
Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v;
}
int dfn[maxp],low[maxp],c[maxp],st[maxp],scc,tim;
void dfs(int u){
st[++st[0]] = u;
dfn[u] = low[u] = ++tim;
for(int i=info[u],v;i;i=Prev[i]) if(!dfn[v=to[i]]) dfs(v),low[u]=min(low[u],low[v]);
else if(!c[v]) low[u] = min(low[u],dfn[v]);
if(dfn[u] == low[u]){
scc++;
for(int t=-1;t!=u;){
t=st[st[0]--];
c[t] = scc;
}
}
}
void Solve(){
int mx[2] = {0,0} , mn[2] = {0x3f3f3f3f,0x3f3f3f3f};
rep(i,1,n) rep(j,0,1)
mn[j] = min(mn[j] , R[i][j]) ,
mx[j] = max(mx[j] , L[i][j]);
int lx[4] = {mn[1] , mn[1] , mn[0] , mn[0]} , rx[4] = {mx[1] , mx[1] , mx[0] , mx[0]};
rep(i,1,n){
vector<int>&s=cs[i];
if(L[i][0] <= mn[0] && mn[0] <= R[i][0]) s.push_back(0);
if(L[i][0] <= mx[0] && mx[0] <= R[i][0]) s.push_back(1);
if(L[i][1] <= mn[1] && mn[1] <= R[i][1]) s.push_back(2);
if(L[i][1] <= mx[1] && mx[1] <= R[i][1]) s.push_back(3);
if(s.size() >= 3) continue;
if(s.size() == 0)return ;
p[i][0] = ++tot , p[i][1] = ++tot;
if(s.size() == 1) Node(p[i][1],p[i][0]);
for(int j=0;j<s.size();j++)
if(s[j] < 2) in[s[j]][max(L[i][1],mn[1])].push_back(p[i][j]),ot[s[j]][min(R[i][1],mx[1])].push_back(p[i][j]);
else in[s[j]][max(L[i][0],mn[0])].push_back(p[i][j]),ot[s[j]][min(R[i][0],mx[0])].push_back(p[i][j]);
}
rep(t,0,3){
int up = 0 , dp = 0;
for(int i=mn[t<2];i<=mx[t<2];i++){
rep(j,0,in[t][i].size()-1)
Node(in[t][i][j],up),Node(dp,in[t][i][j]^1);
Node(++tot , up) , up = tot;
Node(dp , ++tot) , dp = tot;
rep(j,0,ot[t][i].size()-1)
Node(ot[t][i][j],dp),Node(up,ot[t][i][j]^1);
}
}
for(int i=1;i<=tot;i++) if(!dfn[i])
dfs(i);
rep(i,1,n) if(cs[i].size() <= 2){
int u = c[p[i][0]] < c[p[i][1]] ? cs[i][0] : cs[i][1];
if(u < 2) lx[u] = max(lx[u] , L[i][1]) , rx[u] =min(rx[u] , R[i][1]);
else lx[u] = max(lx[u] , L[i][0]) , rx[u] = min(rx[u] , R[i][0]);
}
ans[0][0] = mn[0] , ans[0][1] = lx[0];
ans[1][0] = mx[0] , ans[1][1] = lx[1];
ans[2][1] = mn[1] , ans[2][0] = lx[2];
ans[3][1] = mx[1] , ans[3][0] = lx[3];
for(int i=0;i<K;i++)
printf("%d %d\n",sx[ans[i][0]] , sy[ans[i][1]]);
}
}
int main(){
scanf("%d%d",&n,&K);
for(int i=1;i<=n;i++) scanf("%d%d%d%d",&L[i][0],&L[i][1],&R[i][0],&R[i][1]),sx[++sx[0]]=L[i][0],sx[++sx[0]]=R[i][0],sy[++sy[0]]=L[i][1],sy[++sy[0]]=R[i][1];
sort(sx+1,sx+1+sx[0]),sx[0]=unique(sx+1,sx+1+sx[0])-sx-1;
sort(sy+1,sy+1+sy[0]),sy[0]=unique(sy+1,sy+1+sy[0])-sy-1;
for(int i=1;i<=n;i++) L[i][0]=lower_bound(sx+1,sx+1+sx[0],L[i][0])-sx,R[i][0]=lower_bound(sx+1,sx+1+sx[0],R[i][0])-sx,
L[i][1]=lower_bound(sy+1,sy+1+sy[0],L[i][1])-sy,R[i][1]=lower_bound(sy+1,sy+1+sy[0],R[i][1])-sy;
for(int i=0;i<K;i++) ans[i][0] = ans[i][1] = 1;
Solver1::Solve();
if(K>=4) Solver2::Solve();
}