CF1168C And Reachability

Toad Pimple 有一个整数数组 a 1 , ⋯   , a n a_1,\cdots,a_n a1,,an,我们称 x x x y y y可达当且仅当:

  1. x < y xx<y
  2. 存在一个数组 p p p,其中 x = p 1 < p 2 < . . . < p k = y x=p_1x=p1<p2<...<pk=y,并且对于任意 1 ≤ i < k 1\le i1i<k,满足 a p i & a p i + 1 > 0 a_{p_i}\&a_{p_{i+1}}>0 api&api+1>0

现在给定 Q Q Q组下标 ( X i , Y i ) (X_i,Y_i) (Xi,Yi),请检查它们是否可达。


考虑从 y y y 跳到 x x x,如果我们可以找到一个 a i a_i ai 满足第 j j j 位是 1 1 1 a l a_l al 在这一位也是 1 1 1,并且 r r r 可以跳到这个位置 i i i,就是可行的。

显然,我们要尽可能让这个位置贴近 r r r,因为这样更有“优势”,可以让更多的 l l l 可行。

f i , j f_{i,j} fi,j 表示一个最大的下标 x x x 满足小于等于 i i i a x a_x ax j j j 位是 1 1 1

有朴素转移: f i , j = max ⁡ k = 1 i − 1 f k , j f_{i,j}=\max\limits_{k=1}^{i-1}f_{k,j} fi,j=k=1maxi1fk,j,转移条件 a i & a k > 0 a_i\&a_k>0 ai&ak>0;特殊地,当 a i a_i ai j j j 为是 1 1 1 时, f i , j = i f_{i,j}=i fi,j=i

这是 O ( n 2 ) O(n^2) O(n2) 的,思考如何优化。

发现转移条件 a i & a k > 0 a_i\&a_k>0 ai&ak>0,可以转换为枚举第 x x x 位,如果 a i a_i ai a k a_k ak 的第 x x x 为都为 1 1 1,这样就可以转移。

又有性质 f i , j f_{i,j} fi,j i i i 单调递增,那么肯定是选最大的 k k k 一定最优。

所以用 p r e j pre_j prej 记录当前上一个下标 x x x 满足 a x a_x ax 的第 j j j 位为 1 1 1。转移就变成

f i , j = max ⁡ k = 0 m f p r e k , j f_{i,j}=\max\limits_{k=0}^{m}f_{pre_{k},j} fi,j=k=0maxmfprek,j

对每个 i i i 转移完后记得更新 p r e j pre_j prej

时间复杂度 O ( n log ⁡ 2 n + q log ⁡ n ) O(n\log^2n+q\log n) O(nlog2n+qlogn)

#include
using namespace std;
const int N=3e5+1,NN=19;
int n,q,a[N],f[N][NN+1],pre[NN];
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++){
        for(int j=0;j<NN;j++){
            for(int k=0;k<NN;k++){
                if(a[i]>>k&1){
                    f[i][j]=max(f[i][j],f[pre[k]][j]);
                }
            }
        }
        for(int j=0;j<NN;j++){
            if(a[i]>>j&1){
                pre[j]=i;
                f[i][j]=max(f[i][j],i);
            }
        }
    }
    for(int i=1,x,y;i<=q;i++){
        scanf("%d%d",&x,&y);
        for(int j=0;j<NN;j++){
            if(a[x]>>j&1){
                if(f[y][j]>=x){
                    puts("Shi");
                    goto a;
                }
            }
        }
        puts("Fou");
        a:;
    }
}

你可能感兴趣的:(算法)