[loj3272]汉堡肉
当$k\le 3$,这是一个经典的问题
设所有矩形左下角横纵坐标的最大值为$(x_{1},y_{1})$,右上角横纵坐标的最小值为$(x_{2},y_{2})$,那么必然存在一组合法解满足其中一点为$(x_{1}/x_{2},y_{1}/y_{2})$,不断递归即可,时间复杂度为$o(4^{k}n)$
当$k=4$,我们可以在四条边界线上各放一点来完成
如果一个矩形完全覆盖了一条边(即覆盖了3或4条边,注意覆盖和完全覆盖不同),那么一定含有一个点,因此这类矩形的限制可以删掉
对于剩下的矩形,其覆盖了1或2条边:对于覆盖1条边的,即每一个点有一个范围的限制;对于覆盖2条边的点,分类讨论:
1.相邻的两条边,由于都是前缀/后缀,利用单调性维护
2.相对的两条边,用线段树区间修改,维护出每一个点所对应的合法区间(求交)
根据这个,枚举其中的一个点(离散),则其相邻的一条边上必然有一点选择其所限制的位置,再通过这两个点得到另外两点的限制,最后判断这两个点的限制能否满足(即这两个区间不为空且最相近时能否合法)
时间复杂度为$o(n\log_{2}n+4^{k}n)$,即可通过

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 #define oo 0x3f3f3f3f
5 #define pii pair<int,int>
6 #define mp make_pair
7 #define fi first
8 #define se second
9 #define L (k<<1)
10 #define R (L+1)
11 #define mid (l+r>>1)
12 struct ji{
13 int x1,y1,x2,y2;
14 }a[N];
15 vector<int>vx,vy,vv;
16 vector<pii >ans;
17 int n,m,vis[N],lim1[N],lim2[N],lim3[N],lim4[N];
18 pii f[2][N<<2];
19 void update(pii o,int k){
20 ans.push_back(o);
21 for(int i=1;i<=n;i++)
22 if ((!vis[i])&&(a[i].x1<=o.fi)&&(o.fi<=a[i].x2)&&(a[i].y1<=o.se)&&(o.se<=a[i].y2))vis[i]=k;
23 }
24 void clear(int k){
25 ans.pop_back();
26 for(int i=1;i<=n;i++)
27 if (vis[i]==k)vis[i]=0;
28 }
29 bool dfs(int k){
30 if (k>m){
31 for(int i=1;i<=n;i++)
32 if (!vis[i])return 0;
33 return 1;
34 }
35 ji o=ji{oo,oo,0,0};
36 for(int i=1;i<=n;i++)
37 if (!vis[i]){
38 o.x1=min(o.x1,a[i].x2);
39 o.y1=min(o.y1,a[i].y2);
40 o.x2=max(o.x2,a[i].x1);
41 o.y2=max(o.y2,a[i].y1);
42 }
43 update(mp(o.x1,o.y1),k);
44 if (dfs(k+1))return 1;
45 clear(k);
46 update(mp(o.x1,o.y2),k);
47 if (dfs(k+1))return 1;
48 clear(k);
49 update(mp(o.x2,o.y1),k);
50 if (dfs(k+1))return 1;
51 clear(k);
52 update(mp(o.x2,o.y2),k);
53 if (dfs(k+1))return 1;
54 clear(k);
55 return 0;
56 }
57 void org(vector<int>&v,int l,int r){
58 sort(v.begin(),v.end());
59 vv.clear();
60 for(int i=0;i<v.size();i++)
61 if ((l<=v[i])&&(v[i]<=r)&&((!vv.size())||(v[i]!=vv[vv.size()-1])))vv.push_back(v[i]);
62 v=vv;
63 }
64 pii merge(pii x,pii y){
65 return mp(max(x.fi,y.fi),min(x.se,y.se));
66 }
67 void build(int p,int k,int l,int r,int x){
68 f[p][k]=mp(1,x);
69 if (l==r)return;
70 build(p,L,l,mid,x);
71 build(p,R,mid+1,r,x);
72 }
73 void update(int p,int k,int l,int r,int x,int y,pii z){
74 if ((l>y)||(x>r))return;
75 if ((x<=l)&&(r<=y)){
76 f[p][k]=merge(f[p][k],z);
77 return;
78 }
79 update(p,L,l,mid,x,y,z);
80 update(p,R,mid+1,r,x,y,z);
81 }
82 pii query(int p,int k,int l,int r,int x){
83 if (l==r)return f[p][k];
84 if (x<=mid)return merge(f[p][k],query(p,L,l,mid,x));
85 return merge(f[p][k],query(p,R,mid+1,r,x));
86 }
87 int main(){
88 scanf("%d%d",&n,&m);
89 for(int i=1;i<=n;i++)scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
90 if (dfs(1)){
91 for(int i=0;i<m;i++)printf("%d %d\n",ans[i].fi,ans[i].se);
92 return 0;
93 }
94 ji o=ji{oo,oo,0,0};
95 for(int i=1;i<=n;i++){
96 o.x1=min(o.x1,a[i].x2);
97 o.y1=min(o.y1,a[i].y2);
98 o.x2=max(o.x2,a[i].x1);
99 o.y2=max(o.y2,a[i].y1);
100 }
101 for(int i=1;i<=n;i++){
102 vx.push_back(a[i].x1);
103 vy.push_back(a[i].y1);
104 vx.push_back(a[i].x2);
105 vy.push_back(a[i].y2);
106 }
107 org(vx,o.x1,o.x2);
108 org(vy,o.y1,o.y2);
109 int nx=vx.size(),ny=vy.size();
110 build(0,1,1,ny,nx);
111 build(1,1,1,nx,ny);
112 int l1=0,l2=0;
113 for(int i=1;i<=n;i++){
114 a[i].x1=lower_bound(vx.begin(),vx.end(),a[i].x1)-vx.begin()+1;
115 a[i].x1=min(a[i].x1,nx);
116 a[i].y1=lower_bound(vy.begin(),vy.end(),a[i].y1)-vy.begin()+1;
117 a[i].y1=min(a[i].y1,ny);
118 a[i].x2=lower_bound(vx.begin(),vx.end(),a[i].x2)-vx.begin()+1;
119 a[i].x2=min(a[i].x2,nx);
120 a[i].y2=lower_bound(vy.begin(),vy.end(),a[i].y2)-vy.begin()+1;
121 a[i].y2=min(a[i].y2,ny);
122 }
123 for(int i=1;i<=ny;i++)lim1[i]=lim2[i]=nx;
124 for(int i=1;i<=nx;i++)lim3[i]=ny;
125 for(int i=1;i<=nx;i++)lim4[i]=1;
126 for(int i=1;i<=n;i++){
127 if ((a[i].x1==1)&&(a[i].x2==nx)){
128 if ((a[i].y1==1)||(a[i].y2==ny))continue;
129 update(0,1,1,ny,1,a[i].y1-1,mp(a[i].y1,a[i].y2));
130 update(0,1,1,ny,a[i].y2+1,ny,mp(a[i].y1,a[i].y2));
131 continue;
132 }
133 if ((a[i].y1==1)&&(a[i].y2==ny)){
134 if ((a[i].x1==1)||(a[i].x2==nx))continue;
135 update(1,1,1,nx,1,a[i].x1-1,mp(a[i].x1,a[i].x2));
136 update(1,1,1,nx,a[i].x2+1,nx,mp(a[i].x1,a[i].x2));
137 continue;
138 }
139 if (a[i].x1==1){
140 if (a[i].y1==1)lim1[a[i].y2+1]=min(lim1[a[i].y2+1],a[i].x2);
141 if (a[i].y2==ny)lim2[a[i].y1-1]=min(lim2[a[i].y1-1],a[i].x2);
142 if ((a[i].y1!=1)&&(a[i].y2!=ny)){
143 update(0,1,1,ny,1,a[i].y1-1,mp(nx,1));
144 update(0,1,1,ny,a[i].y2+1,ny,mp(nx,1));
145 }
146 continue;
147 }
148 if (a[i].x2==nx){
149 if (a[i].y1==1)lim3[a[i].x1-1]=min(lim3[a[i].x1-1],a[i].y2);
150 if (a[i].y2==ny)lim4[a[i].x1-1]=max(lim4[a[i].x1-1],a[i].y1);
151 if ((a[i].y1!=1)&&(a[i].y2!=ny))update(0,1,1,ny,1,ny,mp(a[i].y1,a[i].y2));
152 continue;
153 }
154 if (a[i].y1==1){
155 l1=max(l1,a[i].x1);
156 lim1[1]=min(lim1[1],a[i].x2);
157 }
158 if (a[i].y1==ny){
159 l2=max(l2,a[i].x1);
160 lim2[ny]=min(lim2[ny],a[i].x2);
161 }
162 }
163 for(int i=2;i<=ny;i++)lim1[i]=min(lim1[i],lim1[i-1]);
164 for(int i=ny-1;i;i--)lim2[i]=min(lim2[i],lim2[i+1]);
165 for(int i=nx-1;i;i--)lim3[i]=min(lim3[i],lim3[i+1]);
166 for(int i=nx-1;i;i--)lim4[i]=max(lim4[i],lim4[i+1]);
167 for(int i=1;i<=ny;i++){
168 if (!lim1[i])continue;
169 pii o1=query(0,1,1,ny,i),o2=query(1,1,1,nx,lim1[i]);
170 o1.se=min(o1.se,lim3[lim1[i]]);
171 o2.se=min(o2.se,lim2[i]);
172 if ((o1.fi>o1.se)||(o2.fi>o2.se))continue;
173 if (o1.se>=lim4[o2.se]){
174 printf("%d %d\n",vx[0],vy[i-1]);
175 printf("%d %d\n",vx[lim1[i]-1],vy[0]);
176 printf("%d %d\n",vx[nx-1],vy[o1.se-1]);
177 printf("%d %d\n",vx[o2.se-1],vy[ny-1]);
178 return 0;
179 }
180 }
181 for(int i=1;i<=ny;i++){
182 if (!lim2[i])continue;
183 pii o1=query(0,1,1,ny,i),o2=query(1,1,1,nx,lim2[i]);
184 o1.fi=max(o1.fi,lim4[lim2[i]]);
185 o2.se=min(o2.se,lim1[i]);
186 if ((o1.fi>o1.se)||(o2.fi>o2.se))continue;
187 if (o1.fi<=lim3[o2.se]){
188 printf("%d %d\n",vx[0],vy[i-1]);
189 printf("%d %d\n",vx[lim2[i]-1],vy[ny-1]);
190 printf("%d %d\n",vx[nx-1],vy[o1.fi-1]);
191 printf("%d %d\n",vx[o2.se-1],vy[0]);
192 return 0;
193 }
194 }
195 return 0;
196 }
[loj3272]汉堡肉的更多相关文章
- 「JOISC 2020 Day1」汉堡肉
我终于学会打开机房的LOJ了! description LOJ3272 有\(n(n<=2*10^5)\)个矩形,让你找\(k(k<=4)\)个点可以覆盖所有矩形(点可重复),输出一种方案 ...
- JOISC2020 题解
Day1T1 建筑装饰4 题目链接:Day1T1 建筑装饰4 Solution 我们先考虑朴素的\(dp\)方法: 设\(dp_{i,j,k}\)表示前\(i\)个数中,选了\(j\)个\(B\)数组 ...
随机推荐
- 题解 「BJOI2018 治疗之雨」
题目传送门 题目大意 有一个初始为 \(p\) 的数,每次操作分为以下两个: 有 \(\frac{1}{m+1}\) 的概率$+1,但是中途 \(p\) 的最大值只能为 \(n\)$ 有 \(k\) ...
- Dapr-简介及环境搭建
一.Dapr是什么? Dapr 是一个可移植的.事件驱动的运行时,它使任何开发人员能够轻松构建出弹性的.无状态和有状态的应用程序,并可运行在云平台或边缘计算中,它同时也支持多种编程语言和开发框架. 在 ...
- Spring的JDK动态代理如何实现的(源码解析)
前言 上一篇文章中提到了SpringAOP是如何决断使用哪种动态代理方式的,本文接上文讲解SpringAOP的JDK动态代理是如何实现的.SpringAOP的实现其实也是使用了Proxy和Invoca ...
- go-zero 实战之 blog 系统
go-zero 实战项目:blog 本文以 blog 的网站后台为例,着重介绍一下如何使用 go-zero 开发 blog 的用户模块. 本文涉及的所有资料都已上传 github 仓库 kougazh ...
- Java序列初始化
1.数组 Java数组可以用元素集合初始化: char[] c=new char[]{'.','.','.','.'}; 而想要用指定数量的相同元素来初始化数组,可以使用Arrays.fill()方法 ...
- MySQL:基础语法-2
MySQL:基础语法-2 记录一下 MySQL 基础的一些语法,便于查询,该部分内容主要是参考:bilibili 上 黑马程序员 的课程而做的笔记,由于时间有点久了,课程地址忘记了 上文MySQL:基 ...
- [no code] Scrum Meeting 博客目录
项目 内容 2020春季计算机学院软件工程(罗杰 任健) 2020春季计算机学院软件工程(罗杰 任健) 作业要求 Scrum Meeting博客目录 我们在这个课程的目标是 远程协同工作,采用最新技术 ...
- OO第四单元作业总结及课程总结
一.本单元作业架构设计 1.第一次作业 本单元首次接触到UML以及相关概念,在面对第一次作业时首先花了很大功夫去阅读官方接口中各种UmlElement的代码,才理解了输入的模型元素中各属性的含义.总的 ...
- NGINX杂谈——flask_limiter的IP获取(怎么拿到真实的客户端IP)
本篇博客将 flask_limiter 作为切入点,来记录一下自己对 remote_addr 和 proxy_add_x_forwarded_for 两个变量.X-Real-IP 和 X-Forwar ...
- hdu 5175 Misaki's Kiss again(GCD和异或)
题意: 给一个数N. 如果GCD(N,M) = N XOR M,则称M是一个kiss 1<=M<=N 问总共有多少个kiss.并且列出所有的值. 思路: 思路一:枚举M.有大量的GCD ...