当$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. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define N 200005
  4. 4 #define oo 0x3f3f3f3f
  5. 5 #define pii pair<int,int>
  6. 6 #define mp make_pair
  7. 7 #define fi first
  8. 8 #define se second
  9. 9 #define L (k<<1)
  10. 10 #define R (L+1)
  11. 11 #define mid (l+r>>1)
  12. 12 struct ji{
  13. 13 int x1,y1,x2,y2;
  14. 14 }a[N];
  15. 15 vector<int>vx,vy,vv;
  16. 16 vector<pii >ans;
  17. 17 int n,m,vis[N],lim1[N],lim2[N],lim3[N],lim4[N];
  18. 18 pii f[2][N<<2];
  19. 19 void update(pii o,int k){
  20. 20 ans.push_back(o);
  21. 21 for(int i=1;i<=n;i++)
  22. 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. 23 }
  24. 24 void clear(int k){
  25. 25 ans.pop_back();
  26. 26 for(int i=1;i<=n;i++)
  27. 27 if (vis[i]==k)vis[i]=0;
  28. 28 }
  29. 29 bool dfs(int k){
  30. 30 if (k>m){
  31. 31 for(int i=1;i<=n;i++)
  32. 32 if (!vis[i])return 0;
  33. 33 return 1;
  34. 34 }
  35. 35 ji o=ji{oo,oo,0,0};
  36. 36 for(int i=1;i<=n;i++)
  37. 37 if (!vis[i]){
  38. 38 o.x1=min(o.x1,a[i].x2);
  39. 39 o.y1=min(o.y1,a[i].y2);
  40. 40 o.x2=max(o.x2,a[i].x1);
  41. 41 o.y2=max(o.y2,a[i].y1);
  42. 42 }
  43. 43 update(mp(o.x1,o.y1),k);
  44. 44 if (dfs(k+1))return 1;
  45. 45 clear(k);
  46. 46 update(mp(o.x1,o.y2),k);
  47. 47 if (dfs(k+1))return 1;
  48. 48 clear(k);
  49. 49 update(mp(o.x2,o.y1),k);
  50. 50 if (dfs(k+1))return 1;
  51. 51 clear(k);
  52. 52 update(mp(o.x2,o.y2),k);
  53. 53 if (dfs(k+1))return 1;
  54. 54 clear(k);
  55. 55 return 0;
  56. 56 }
  57. 57 void org(vector<int>&v,int l,int r){
  58. 58 sort(v.begin(),v.end());
  59. 59 vv.clear();
  60. 60 for(int i=0;i<v.size();i++)
  61. 61 if ((l<=v[i])&&(v[i]<=r)&&((!vv.size())||(v[i]!=vv[vv.size()-1])))vv.push_back(v[i]);
  62. 62 v=vv;
  63. 63 }
  64. 64 pii merge(pii x,pii y){
  65. 65 return mp(max(x.fi,y.fi),min(x.se,y.se));
  66. 66 }
  67. 67 void build(int p,int k,int l,int r,int x){
  68. 68 f[p][k]=mp(1,x);
  69. 69 if (l==r)return;
  70. 70 build(p,L,l,mid,x);
  71. 71 build(p,R,mid+1,r,x);
  72. 72 }
  73. 73 void update(int p,int k,int l,int r,int x,int y,pii z){
  74. 74 if ((l>y)||(x>r))return;
  75. 75 if ((x<=l)&&(r<=y)){
  76. 76 f[p][k]=merge(f[p][k],z);
  77. 77 return;
  78. 78 }
  79. 79 update(p,L,l,mid,x,y,z);
  80. 80 update(p,R,mid+1,r,x,y,z);
  81. 81 }
  82. 82 pii query(int p,int k,int l,int r,int x){
  83. 83 if (l==r)return f[p][k];
  84. 84 if (x<=mid)return merge(f[p][k],query(p,L,l,mid,x));
  85. 85 return merge(f[p][k],query(p,R,mid+1,r,x));
  86. 86 }
  87. 87 int main(){
  88. 88 scanf("%d%d",&n,&m);
  89. 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. 90 if (dfs(1)){
  91. 91 for(int i=0;i<m;i++)printf("%d %d\n",ans[i].fi,ans[i].se);
  92. 92 return 0;
  93. 93 }
  94. 94 ji o=ji{oo,oo,0,0};
  95. 95 for(int i=1;i<=n;i++){
  96. 96 o.x1=min(o.x1,a[i].x2);
  97. 97 o.y1=min(o.y1,a[i].y2);
  98. 98 o.x2=max(o.x2,a[i].x1);
  99. 99 o.y2=max(o.y2,a[i].y1);
  100. 100 }
  101. 101 for(int i=1;i<=n;i++){
  102. 102 vx.push_back(a[i].x1);
  103. 103 vy.push_back(a[i].y1);
  104. 104 vx.push_back(a[i].x2);
  105. 105 vy.push_back(a[i].y2);
  106. 106 }
  107. 107 org(vx,o.x1,o.x2);
  108. 108 org(vy,o.y1,o.y2);
  109. 109 int nx=vx.size(),ny=vy.size();
  110. 110 build(0,1,1,ny,nx);
  111. 111 build(1,1,1,nx,ny);
  112. 112 int l1=0,l2=0;
  113. 113 for(int i=1;i<=n;i++){
  114. 114 a[i].x1=lower_bound(vx.begin(),vx.end(),a[i].x1)-vx.begin()+1;
  115. 115 a[i].x1=min(a[i].x1,nx);
  116. 116 a[i].y1=lower_bound(vy.begin(),vy.end(),a[i].y1)-vy.begin()+1;
  117. 117 a[i].y1=min(a[i].y1,ny);
  118. 118 a[i].x2=lower_bound(vx.begin(),vx.end(),a[i].x2)-vx.begin()+1;
  119. 119 a[i].x2=min(a[i].x2,nx);
  120. 120 a[i].y2=lower_bound(vy.begin(),vy.end(),a[i].y2)-vy.begin()+1;
  121. 121 a[i].y2=min(a[i].y2,ny);
  122. 122 }
  123. 123 for(int i=1;i<=ny;i++)lim1[i]=lim2[i]=nx;
  124. 124 for(int i=1;i<=nx;i++)lim3[i]=ny;
  125. 125 for(int i=1;i<=nx;i++)lim4[i]=1;
  126. 126 for(int i=1;i<=n;i++){
  127. 127 if ((a[i].x1==1)&&(a[i].x2==nx)){
  128. 128 if ((a[i].y1==1)||(a[i].y2==ny))continue;
  129. 129 update(0,1,1,ny,1,a[i].y1-1,mp(a[i].y1,a[i].y2));
  130. 130 update(0,1,1,ny,a[i].y2+1,ny,mp(a[i].y1,a[i].y2));
  131. 131 continue;
  132. 132 }
  133. 133 if ((a[i].y1==1)&&(a[i].y2==ny)){
  134. 134 if ((a[i].x1==1)||(a[i].x2==nx))continue;
  135. 135 update(1,1,1,nx,1,a[i].x1-1,mp(a[i].x1,a[i].x2));
  136. 136 update(1,1,1,nx,a[i].x2+1,nx,mp(a[i].x1,a[i].x2));
  137. 137 continue;
  138. 138 }
  139. 139 if (a[i].x1==1){
  140. 140 if (a[i].y1==1)lim1[a[i].y2+1]=min(lim1[a[i].y2+1],a[i].x2);
  141. 141 if (a[i].y2==ny)lim2[a[i].y1-1]=min(lim2[a[i].y1-1],a[i].x2);
  142. 142 if ((a[i].y1!=1)&&(a[i].y2!=ny)){
  143. 143 update(0,1,1,ny,1,a[i].y1-1,mp(nx,1));
  144. 144 update(0,1,1,ny,a[i].y2+1,ny,mp(nx,1));
  145. 145 }
  146. 146 continue;
  147. 147 }
  148. 148 if (a[i].x2==nx){
  149. 149 if (a[i].y1==1)lim3[a[i].x1-1]=min(lim3[a[i].x1-1],a[i].y2);
  150. 150 if (a[i].y2==ny)lim4[a[i].x1-1]=max(lim4[a[i].x1-1],a[i].y1);
  151. 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. 152 continue;
  153. 153 }
  154. 154 if (a[i].y1==1){
  155. 155 l1=max(l1,a[i].x1);
  156. 156 lim1[1]=min(lim1[1],a[i].x2);
  157. 157 }
  158. 158 if (a[i].y1==ny){
  159. 159 l2=max(l2,a[i].x1);
  160. 160 lim2[ny]=min(lim2[ny],a[i].x2);
  161. 161 }
  162. 162 }
  163. 163 for(int i=2;i<=ny;i++)lim1[i]=min(lim1[i],lim1[i-1]);
  164. 164 for(int i=ny-1;i;i--)lim2[i]=min(lim2[i],lim2[i+1]);
  165. 165 for(int i=nx-1;i;i--)lim3[i]=min(lim3[i],lim3[i+1]);
  166. 166 for(int i=nx-1;i;i--)lim4[i]=max(lim4[i],lim4[i+1]);
  167. 167 for(int i=1;i<=ny;i++){
  168. 168 if (!lim1[i])continue;
  169. 169 pii o1=query(0,1,1,ny,i),o2=query(1,1,1,nx,lim1[i]);
  170. 170 o1.se=min(o1.se,lim3[lim1[i]]);
  171. 171 o2.se=min(o2.se,lim2[i]);
  172. 172 if ((o1.fi>o1.se)||(o2.fi>o2.se))continue;
  173. 173 if (o1.se>=lim4[o2.se]){
  174. 174 printf("%d %d\n",vx[0],vy[i-1]);
  175. 175 printf("%d %d\n",vx[lim1[i]-1],vy[0]);
  176. 176 printf("%d %d\n",vx[nx-1],vy[o1.se-1]);
  177. 177 printf("%d %d\n",vx[o2.se-1],vy[ny-1]);
  178. 178 return 0;
  179. 179 }
  180. 180 }
  181. 181 for(int i=1;i<=ny;i++){
  182. 182 if (!lim2[i])continue;
  183. 183 pii o1=query(0,1,1,ny,i),o2=query(1,1,1,nx,lim2[i]);
  184. 184 o1.fi=max(o1.fi,lim4[lim2[i]]);
  185. 185 o2.se=min(o2.se,lim1[i]);
  186. 186 if ((o1.fi>o1.se)||(o2.fi>o2.se))continue;
  187. 187 if (o1.fi<=lim3[o2.se]){
  188. 188 printf("%d %d\n",vx[0],vy[i-1]);
  189. 189 printf("%d %d\n",vx[lim2[i]-1],vy[ny-1]);
  190. 190 printf("%d %d\n",vx[nx-1],vy[o1.fi-1]);
  191. 191 printf("%d %d\n",vx[o2.se-1],vy[0]);
  192. 192 return 0;
  193. 193 }
  194. 194 }
  195. 195 return 0;
  196. 196 }

[loj3272]汉堡肉的更多相关文章

  1. 「JOISC 2020 Day1」汉堡肉

    我终于学会打开机房的LOJ了! description LOJ3272 有\(n(n<=2*10^5)\)个矩形,让你找\(k(k<=4)\)个点可以覆盖所有矩形(点可重复),输出一种方案 ...

  2. JOISC2020 题解

    Day1T1 建筑装饰4 题目链接:Day1T1 建筑装饰4 Solution 我们先考虑朴素的\(dp\)方法: 设\(dp_{i,j,k}\)表示前\(i\)个数中,选了\(j\)个\(B\)数组 ...

随机推荐

  1. Network Analyst Tools(Network Analyst 工具)

    Network Analyst 工具 1.分析 # Process: 创建 OD 成本矩阵图层 arcpy.MakeODCostMatrixLayer_na("", "O ...

  2. app定位工具介绍

     一.元素获取工具WEditor使用   1.安装WEditor:pip3 install weditor   2.启动WEditor:python3 -m weditor    Android : ...

  3. HTML中的emment

    emment的优点和使用方法: 优点:Emment是前端开发者必备的工具,使用它可以大大提高前端开发效率. 使用方法:Emment的使用方法非常简单,直接在编辑器上输入HTML和CSS代码的缩写,然后 ...

  4. Beta阶段性总结

    1.题士开发总结 2.反思 2.1 Issue管理 从0522敲定各个功能的API后,团队成员及时沟通,积极开发,但由于开发过程没能有效体现在issue上(如未能及时在issue上形成记录,功能开发完 ...

  5. 混合开发框架Flutter

    Flutter开发简介与其他的混合开发的对比 为什么要使用Flutter? 跨平台技术简介 Hybrid技术简介 QT简介 Flutter简介 为什么要使用Flutter? Flutter有什么优势? ...

  6. Vue项目搭建常用的配置文件,request.js和vue.config.js

    request.js用来请求数据,封装的代码如下: import axios from 'axios' const request = axios.create({ timeout: 5000 }) ...

  7. 2021.8.11考试总结[NOIP模拟36]

    T1 Dove玩扑克 考场并查集加树状数组加桶期望$65pts$实际$80pts$,考后多开个数组记哪些数出现过,只扫出现过的数就切了.用$set$维护可以把被删没的数去掉,更快. $code:$ 1 ...

  8. stm32f103系列引脚定义-功能图

    器件功能和配置(STM32F103xx增强型) STM32F103xx增强型模块框架图 STM32F103xx增强型VFQFPN36管脚图 STM32F103xx增强型LQFP100管脚图 STM32 ...

  9. NavigationView使用简介

    Android支持直接创建带有NavigationView的Activity,这里主要介绍NavigationView的逻辑. NavigationView通常是跟DrawerLayout一起使用.D ...

  10. Register Abstraction(9)

    This post will explain how to use the UVM Register Abstraction Layer (RAL) to generate register tran ...