[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\)数组 ...
随机推荐
- Network Analyst Tools(Network Analyst 工具)
Network Analyst 工具 1.分析 # Process: 创建 OD 成本矩阵图层 arcpy.MakeODCostMatrixLayer_na("", "O ...
- app定位工具介绍
一.元素获取工具WEditor使用 1.安装WEditor:pip3 install weditor 2.启动WEditor:python3 -m weditor Android : ...
- HTML中的emment
emment的优点和使用方法: 优点:Emment是前端开发者必备的工具,使用它可以大大提高前端开发效率. 使用方法:Emment的使用方法非常简单,直接在编辑器上输入HTML和CSS代码的缩写,然后 ...
- Beta阶段性总结
1.题士开发总结 2.反思 2.1 Issue管理 从0522敲定各个功能的API后,团队成员及时沟通,积极开发,但由于开发过程没能有效体现在issue上(如未能及时在issue上形成记录,功能开发完 ...
- 混合开发框架Flutter
Flutter开发简介与其他的混合开发的对比 为什么要使用Flutter? 跨平台技术简介 Hybrid技术简介 QT简介 Flutter简介 为什么要使用Flutter? Flutter有什么优势? ...
- Vue项目搭建常用的配置文件,request.js和vue.config.js
request.js用来请求数据,封装的代码如下: import axios from 'axios' const request = axios.create({ timeout: 5000 }) ...
- 2021.8.11考试总结[NOIP模拟36]
T1 Dove玩扑克 考场并查集加树状数组加桶期望$65pts$实际$80pts$,考后多开个数组记哪些数出现过,只扫出现过的数就切了.用$set$维护可以把被删没的数去掉,更快. $code:$ 1 ...
- stm32f103系列引脚定义-功能图
器件功能和配置(STM32F103xx增强型) STM32F103xx增强型模块框架图 STM32F103xx增强型VFQFPN36管脚图 STM32F103xx增强型LQFP100管脚图 STM32 ...
- NavigationView使用简介
Android支持直接创建带有NavigationView的Activity,这里主要介绍NavigationView的逻辑. NavigationView通常是跟DrawerLayout一起使用.D ...
- Register Abstraction(9)
This post will explain how to use the UVM Register Abstraction Layer (RAL) to generate register tran ...