[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 }