CF1181E2 A Story of One Country (Hard) 题解
\(O(n \log n)\) 的做法。
\(O(n \log^ 2n)\) 的做法不过多赘述,我们还是先存下来所有矩形按照四种方式排序后的结果。
与原来做法不同的是,我们找到一个缝隙之后,不是立刻递归子问题,而是将要分裂出来的部分先打上一个颜色标记,然后从头开始重新扫描一遍,如果扫描过程中遇到有颜色的位置再用链表删除。当前子问题中,每个位置只会被删除一次。
重复扫描的过程,直到剩余部分 \(\le 3\)。此时再遍历当前所有的矩形,按照给他染上的颜色分类并递归子问题,因为是按照原顺序扫的所以无需排序。
上面整个部分是关于子问题大小线性的,类似原做法,递归子问题后,一定不存在一个子问题的大小 \(> \dfrac{n}{2}\),因此只会递归 \(O(\log n)\) 层,时间复杂度为 \(O(n\log n)\)。
应该没问题吧。下面是写的有点烂的代码:
代码
#include<bits/stdc++.h>
const int N=1e5+5,INF=1e9;
int n;
struct NODE{int xl,xr,yl,yr;}p[N];
struct node{
int l,r,id;
node(int _l=0,int _r=0,int _id=0){l=_l,r=_r,id=_id;}
bool friend operator<(node a,node b){
if(a.l==b.l&&a.r==b.r)return a.id<b.id;
return a.l==b.l?a.r<b.r:a.l<b.l;
}
}a[4][N];
int nxt[4][N],id[4][N];
int col[N],inq[N];
std::vector<int> vec[N][4];
inline void Solve(){
rd(n);
std::queue<int> q;
auto Tr=[&](int t,int id){
if(t==0)return node(p[id].xl,p[id].xr,id);
if(t==1)return node(-p[id].xr,-p[id].xl,id);
if(t==2)return node(p[id].yl,p[id].yr,id);
if(t==3)return node(-p[id].yr,-p[id].yl,id);
return node();
};
for(int i=0;i<=n;i++)col[i]=inq[i]=0;
for(int i=0;i<=n;i++)
for(int t=0;t<4;t++)vec[i][t].clear();
for(int i=1;i<=n;i++){
rd(p[i].xl,p[i].yl,p[i].xr,p[i].yr);
for(int t=0;t<4;t++)a[t][i]=Tr(t,i);
for(int t=0;t<4;t++)id[t][i]=i;
}
for(int t=0;t<4;t++){
id[t][n+1]=n+1;
std::sort(id[t]+1,id[t]+n+1,[&](int x,int y){return a[t][x]<a[t][y];});
for(int i=1;i<=n;i++)vec[0][t].push_back(id[t][i]);
}
q.push(0);
int cnt=0;
while(!q.empty()){
int x=q.front();q.pop();
int len=(int)vec[x][0].size();
if(vec[x][0].size()<=3)continue;
int now=0;
for(int t=0;t<4;t++){
for(int i=0;i<=len;i++)
nxt[t][i]=i+1;
}
auto Next=[&](int t,int i){
int j;
for(j=nxt[t][i];j!=len+1;j=nxt[t][j]){
if(col[vec[x][t][j-1]]==x)break;
}
nxt[t][i]=j;
return j;
};
while(now+3<len){
int flag=0;
int it[4]={0,0,0,0},cur[4]={-INF,-INF,-INF,-INF};
while(1){
for(int t=0;t<4;t++)it[t]=Next(t,it[t]);
if(Next(0,it[0])==len+1)break;
for(int t=0;t<4;t++)cur[t]=std::max(cur[t],a[t][vec[x][t][it[t]-1]].r);
for(int t=0;t<4;t++){
if(cur[t]<=a[t][vec[x][t][Next(t,it[t])-1]].l){
int nowp=0,ed=Next(t,it[t]);
++cnt;
while(1){
nowp=Next(t,nowp);
if(nowp==ed)break;
col[vec[x][t][nowp-1]]=cnt;
++now;
}
flag=1;
break;
}
}
if(flag)break;
}
if(!flag){
puts("NO");
return ;
}
}
for(int t=0;t<4;t++){
for(int i=0;i<len;i++){
int k=vec[x][t][i];
if(col[k]!=x){
vec[col[k]][t].push_back(k);
if(!inq[col[k]])inq[col[k]]=1,q.push(col[k]);
}
}
}
}
puts("YES");
}
signed main(){
Solve();
return 0;
}

浙公网安备 33010602011771号