题解:AT_abc457_e [ABC457E] Crossing Table Cloth

· · 题解

题意概述:

不难发现,对于询问 $S,T$,选择两块布 $i,j$ 满足题目条件,不妨设 $l_i\le l_j$,该方案必然属于以下两种方案之一: - 方案一:$S=l_i\le l_j-1\le r_i<r_j=T$。即,布 $i$ 覆盖 $S$ 而不覆盖 $T$,布 $j$ 覆盖 $T$ 而不覆盖 $S$,布 $i,j$ 覆盖 $\left[S,T\right]$。这里不用考虑 $i,j$ 是否相等,因为 $l_i\le l_j-1$ 就已经决定了 $i\ne j$。 - 方案二:$i\ne j,S=l_i\le l_j\le r_j\le r_i=T$。即,布 $i$ 只覆盖 $\left[S,T\right]$,布 $j$ 覆盖在 $\left[S,T\right]$ 之内,且两布不相等。这里,只是说 $i\ne j$,不代表 $l_i\ne l_j,r_i\ne r_j$。 两种方案交集为空,并集为所有满足题目条件的方案。 不难发现,两种方案都要用到以 $S$ 为左端点的布,和以 $T$ 为右端点的布,因此考虑用 $a_l$ 存储所有以 $l$ 为左端点的布的右端点 $r$,用 $b_r$ 存储所有以 $r$ 为右端点的布的左端点 $l$,其内部从小到大排序,注意不可以去重,即使有重复的也可以在方案二里用到。 对于方案一,贪心地让 $r_i$ 尽可能大,$l_j$ 尽可能小,只要 $r_i<T$ 的最大 $r_i$ 与 $l_j>S$ 的最小 $l_j$ 满足 $l_j-1\le r_i$,那么就是合法的。这可以通过二分查找来实现。 对于方案二,首先需要满足存在**至少**一块布的覆盖区间为 $\left[S,T\right]$,其次需要快速判断区间 $\left[S,T\right]$ 内是否存在布 $j$ 满足 $S\le l_j\le r_j\le T$ 且 $i\ne j$。转换一下: - 存在**至少**两块布的覆盖区间为 $\left[S,T\right]$,此时必然合法。 - 不存在布的覆盖区间为 $\left[S,T\right]$,此时必然不合法。 - 存在**恰好**一块布的覆盖区间为 $\left[S,T\right]$,并且存在布 $j$ 满足 $S\le l_j\le r_j<T$ 或 $S<l_j\le r_j\le T$。 对于前两种情况,可以开个 map 记录所有覆盖区间的个数。 对于第三种情况,我们先考虑条件一:存在布 $j$ 满足 $S\le l_j\le r_j<T$。 换句话说,就是在所有左端点大于或等于 $S$ 的布中,最小右端点需要小于 $T$。 设函数 $f_r\left(l\right)$ 表示以 $l$ 为左端点的布中的最小右端点,函数 $g_r\left(l\right)$ 表示左端点大于或等于 $l$ 的布中的最小右端点,那么 $g_r\left(l\right)$ 就是 $f_r\left(l\right)$ 的后缀最小值,即: $$g_r\left(l\right)=\min\limits_{i=l}^n f_r\left(i\right)=\min\left(g_r\left(l+1\right),f_r\left(l\right)\right)$$ 读入时预处理 $f_r$ 函数,然后从后往前枚举 $l$ 即可预处理得到 $g_r$ 函数。 当 $g_r\left(S\right)<T$ 时,条件一成立;否则不成立。 考虑条件二:存在布 $j$ 满足 $S\le l_j\le r_j<T$。 换句话说,就是在所有右端点小于或等于 $T$ 的布中,最大左端点需要大于 $S$。 设函数 $f_l\left(r\right)$ 表示以 $r$ 为右端点的布中的最大左端点,函数 $g_l\left(r\right)$ 表示右端点小于或等于 $r$ 的布中的最大左端点,同理可以读入时预处理 $f_l$ 函数,然后从前往后枚举 $r$ 预处理得到 $g_l$ 函数: $$g_l\left(r\right)=\max\limits_{i=1}^r f_l\left(i\right)=\max\left(g_l\left(r-1\right),f_l\left(r\right)\right)$$ 当 $g_l\left(T\right)>S$ 时,条件二成立;否则不成立。 当两个条件满足至少一个时,第三种情况合法;否则不合法。 方案一、二同样只要满足其一,答案即为 `Yes`;否则答案为 `No`。 代码如下: ```c++ typedef pair<int,int> pir; const int N=200005; int n,m; int fr[N],gr[N],fl[N],gl[N]; vector<int> a[N],b[N]; map<pir,int> cnt; int q,S,T; inline bool proposal_1() { // 方案一 int ri=0,lj=0; auto it_ri=lower_bound(a[S].begin(),a[S].end(),T); if(it_ri==a[S].begin()) return false; it_ri--,ri=*it_ri; auto it_lj=upper_bound(b[T].begin(),b[T].end(),S); if(it_lj==b[T].end()) return false; lj=*it_lj; return lj-1<=ri; } inline bool proposal_2() { // 方案二 int t=cnt[{S,T}]; if(t>=2) return true; if(!t) return false; return gr[S]<T||gl[T]>S; } int main() { memset(fr,0x3f,sizeof(fr)); memset(fl,0,sizeof(fl)); n=read(),m=read(); for(int i=1;i<=m;i++) { int l=read(),r=read(); fr[l]=min(fr[l],r); fl[r]=max(fl[r],l); a[l].push_back(r); b[r].push_back(l); cnt[{l,r}]++; } gr[n]=fr[n]; for(int l=n-1;l;l--) gr[l]=min(gr[l+1],fr[l]); gl[1]=fl[1]; for(int r=2;r<=n;r++) gl[r]=max(gl[r-1],fl[r]); for(int i=1;i<=n;i++) sort(a[i].begin(),a[i].end()),sort(b[i].begin(),b[i].end()); q=read(); for(int i=1;i<=q;i++) { S=read(),T=read(); if(proposal_1()||proposal_2()) puts("Yes"); else puts("No"); } return 0; } ```