AT_abc457_e 解题报告

· · 题解

AT_abc457_e 解题报告

作者提示:相接定义为 x \ge y,或两者刚好相邻。

形式化题面

给你 n 个格子和 m 块布,第 i 块布覆盖 [l_i,r_i] 这个区间。

回答 q 个问题,第 i 个问题给出 s_it_i,让你求出能否用两块布恰好覆盖 [s_i,t_i] 这个区间,而不覆盖其他任何格子。

分析

这两块布的覆盖可以分为两种情况:

  1. 一个覆盖 [s,x],另一个覆盖 [y,t],还需满足 xt 相接(不是单纯的符号关系)。我就是因为这个找半天没找出来。

  2. 有一个区间直接覆盖 [s,t],直接找出另一个区间被 [s,t] 包含即可。

判断

对于第一种情况,我们要找出 x 在小于等于 t 的情况下的最大值和 y 在大于等于 s 下的最小值,若被查到的都是一个区间,就说明该区间就是 [s,t]。可以直接判断有没有另一个区间被 [s,t] 包含,不然就判断是否相接。

算法分析

找在这些约束条件下的最大值可以直接用二分写。

至于包含,只要枚举开始编号即可。

算法复杂度

~~很丑。~~ ## 代码 ``` cpp #include <bits/stdc++.h> using namespace std; typedef long long ll; #define fastio ios::sync_with_stdio(0);cin.tie(0),cout.tie(0) #define endl "\n" const int N=2e5+5; int n,m,q; struct ridx{ int to,idx; }; vector<ridx> ltor[N],rtol[N]; bool cmp1(ridx x,ridx y){ return x.to<y.to; } bool cmp2(ridx x,ridx y){ return x.to>y.to; } bool bh(int s,int t){ int cnt=0; for(int i=s;i<=t;i++){ if(ltor[i].empty()) continue; int ans=-1; int l,r; l=0,r=ltor[i].size()-1; while(l<=r){ int mid=(l+r)>>1; if(ltor[i][mid].to<=t){ ans=mid; l=mid+1; } else{ r=mid-1; } } ans++; cnt+=ans; if(cnt>1){ return true; } } return false; } bool query(int s,int t){ if(ltor[s].empty()||rtol[t].empty()){ return false; } int totj=-1,totans,totid; int l,r; l=0,r=ltor[s].size()-1; while(l<=r){ int mid=(l+r)>>1; if(ltor[s][mid].to<=t){ totj=mid; l=mid+1; } else{ r=mid-1; } } if(totj==-1) return false; totans=ltor[s][totj].to; totid=ltor[s][totj].idx; int tosj=-1,tosans,tosid; l=0,r=rtol[t].size()-1; while(l<=r){ int mid=(l+r)>>1; if(rtol[t][mid].to>=s){ tosj=mid; l=mid+1; } else{ r=mid-1; } } if(tosj==-1) return false; tosans=rtol[t][tosj].to; tosid=rtol[t][tosj].idx; if(totid==tosid){ return bh(s,t); } return totans>=tosans-1; } int main(){ fastio; cin>>n>>m; for(int i=1;i<=m;i++){ int l,r; cin>>l>>r; ltor[l].push_back({r,i}); rtol[r].push_back({l,i}); } for(int i=1;i<=n;i++){ if(!ltor[i].empty()){ sort(ltor[i].begin(),ltor[i].end(),cmp1); } if(!rtol[i].empty()){ sort(rtol[i].begin(),rtol[i].end(),cmp2); } } cin>>q; while(q--){ int s,t; cin>>s>>t; if(query(s,t)){ cout<<"Yes\n"; } else{ cout<<"No\n"; } } return 0; } ```