题解:
如果你不去看数据范围很容易就觉得这是一道不可做题。
感觉如果 K K K 再大一点也可能就是 NP-Hard 了。
首先求出左边界最大值 m x L mxL mxL,右边界最小值 m n R mnR mnR,上边界最小值 m n U mnU mnU 和下边界最大值 m x D mxD mxD,显然任何一组解都可以通过平移走到这几条直线上。
当 K ≤ 3 K\leq 3 K≤3 的时候由抽屉原理可知必然有至少一个点在这几条线的交点处,暴力dfs即可。
当 K = 4 K=4 K=4 的时候,我们还是选择先暴力 dfs ,如果没有找到答案,说明 m x L < m n R , m x D < m n U mxL<mnR,mxD<mnU mxL<mnR,mxD<mnU。
显然答案的四根竹签应该分别在这四条线上。
如果某个矩形与这四条线中的至少三条相交,说明它完全包含了某条线段,否则它应该更新这四个值中的一个,则我们可以不考虑这个矩形。
剩下的矩形都与这四条线中的 1 − 2 1-2 1−2 条相交,如果只与一条相交,则该直线的上的竹签必然存在于某个确定的区间中。
否则如果与两条直线相交,我们可以将这个转化为 2-SAT 问题,设这两条线上的点未确定的坐标为 x 1 , x 2 x_1,x_2 x1,x2,则要求某一个矩形包含至少一个点可以转化为 x 1 ∈ [ l 1 , r 1 ] ∨ x 2 ∈ [ l 2 , r 2 ] x_1\in[l_1,r_1]\lor x_2\in[l_2,r_2] x1∈[l1,r1]∨x2∈[l2,r2],对于每个直线上的限制,离散化后前缀连边的套路就不讨论了,考虑怎么处理对于某个矩形的限制。
对于这个矩形,建立两个变量 y 1 , . y 2 y_1,.y_2 y1,.y2 四个点,分别表示它在两条直线上的限制是否满足,有限制 y 1 ∣ ∣ y 2 y_1||y_2 y1∣∣y2 为真,连边 ¬ y 1 → y 2 \neg y_1\rightarrow y_2 ¬y1→y2, ¬ y 2 → y 1 \neg y_2\rightarrow y_1 ¬y2→y1,然后前后缀该怎么满足怎么连边就行了。
下面的代码连边经过了优化,并没有把 y 1 , y 2 y_1,y_2 y1,y2 四个点建立出来,如果需要判断是否有解的话可能就必须要建立出来了。
跑 2-SAT 即可
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}template<typename T>T get_integer(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
}inline int gi(){return get_integer<int>();}
}using namespace IO;
using std::cerr;
using std::cout;
using pii=std::pair<int,int>;
#define fi first
#define se second
template<typename T>void ckmn(T &a,cs T &b){a>b?a=b:a;}
template<typename T>void ckmx(T &a,cs T &b){a<b?a=b:a;}
cs int N=2e6+7;
cs int INF=1e9;
int n,k;
struct rec{int x1,x2,y1,y2;};
std::vector<rec> vec;
std::vector<rec> rem(cs std::vector<rec> &vec,int x,int y){
std::vector<rec> res;
for(cs auto &t:vec)
if(t.x1>x||t.x2<x||t.y1>y||t.y2<y)
res.push_back(t);
return res;
}
bool dfs(cs std::vector<rec> &vec,int k){
if(vec.empty()){
while(k--)cout<<"0 0\n";
return true;
}if(!k)return false;
int L=0,R=INF,D=0,U=INF;
for(cs auto &t:vec){
ckmx(L,t.x1),ckmn(R,t.x2);
ckmx(D,t.y1),ckmn(U,t.y2);
}
if(dfs(rem(vec,L,D),k-1))
return cout<<L<<" "<<D<<"\n",1;
if(dfs(rem(vec,L,U),k-1))
return cout<<L<<" "<<U<<"\n",1;
if(dfs(rem(vec,R,D),k-1))
return cout<<R<<" "<<D<<"\n",1;
if(dfs(rem(vec,R,U),k-1))
return cout<<R<<" "<<U<<"\n",1;
return false;
}
std::vector<int> G[N];
int id[N][2],ct;
bool ok[N];
int dfn[N],low[N];
int scc[N],sct,dfc;
int st[N],tp,ins[N];
void tarjan(int u){
dfn[u]=low[u]=++dfc;
ins[u]=true;st[++tp]=u;
for(int v:G[u]){
if(!dfn[v])tarjan(v),low[u]=std::min(low[u],low[v]);
else if(ins[v])low[u]=std::min(low[u],dfn[v]);
}if(dfn[u]!=low[u])return ;++sct;
do scc[st[tp]]=sct,ins[st[tp]]=false;while(st[tp--]!=u);
}
void Main(){
n=gi(),k=gi();vec.resize(n);
for(auto &t:vec)
t.x1=gi(),t.y1=gi(),
t.x2=gi(),t.y2=gi();
if(dfs(vec,k))return ;
int x[2]={0,INF},y[2]={0,INF};ct=n<<1;
for(auto &t:vec){
ckmx(x[0],t.x1),ckmn(x[1],t.x2);
ckmx(y[0],t.y1),ckmn(y[1],t.y2);
}for(int re i=0;i<n;++i){
bool f[4]={
vec[i].x2>=x[0],vec[i].x1<=x[1],
vec[i].y2>=y[0],vec[i].y1<=y[1]
};if(f[0]+f[1]+f[2]+f[3]>2){
ok[i]=true;id[i][0]=id[i][1]=-1;
}else {
int ct=0;for(int re j=0;j<4;++j)
if(f[j])id[i][ct++]=j;
if(ct==1)
id[i][1]=-1,G[i<<1|1].push_back(i<<1);
}
}for(int re i=0;i<4;++i){
std::vector<int> pt;
std::priority_queue<pii> q;
for(int j=0;j<n;++j)
if(id[j][0]==i||id[j][1]==i)
pt.push_back(j);
std::sort(pt.begin(),pt.end(),[i](int a,int b){
return i<2?vec[a].y1<vec[b].y1:vec[a].x1<vec[b].x1;
});int p1=-1,p2=-1;
for(int u:pt){
q.push(pii(i<2?-vec[u].y2:-vec[u].x2,u));
while(-q.top().fi<(i<2?vec[u].y1:vec[u].x1)){
int p=q.top().se;q.pop();bool t=id[p][1]==i;
if(p1==-1)p1=p<<1|t,p2=p1^1;
else {
G[p<<1|t].push_back(ct);
G[p1].push_back(ct);p1=ct++;
G[ct].push_back(p<<1|!t);
G[ct].push_back(p2);p2=ct++;
}
}
if(p1!=-1){
bool t=id[u][1]==i;
G[u<<1|t].push_back(p2);
G[p1].push_back(u<<1|!t);
}
}
}
for(int re i=0;i<ct;++i)
if(!dfn[i])tarjan(i);
int ans[4][2]={};
for(int re i=0;i<n;++i)if(!ok[i]){
int p=id[i][scc[i<<1]>scc[i<<1|1]];
ans[p][0]=std::max(ans[p][0],vec[i].x1);
ans[p][1]=std::max(ans[p][1],vec[i].y1);
}for(int re i=0;i<2;++i)
cout<<x[i]<<" "<<ans[i][1]<<"\n";
for(int re i=2;i<4;++i)
cout<<ans[i][0]<<" "<<y[i-2]<<"\n";
}
inline void file(){
#ifdef zxyoi
freopen("hamburg.in","r",stdin);
#endif
}signed main(){file();Main();return 0;}