CF1168C And Reachability [structure, dp]

Posted by icedude on Fri, 01 Nov 2019 16:39:38 +0100

Title Link: Luo Gu

Title Description: give the number of $n $$a_i $, if $I < J $and $a_i & a_j > 0 $, then $I $to $J $are connected with a directed side, $q $times, and ask if it can reach $r $from $l $.

Data range: $n,q\leq 3*10^5$

A wonderful thought problem. (binary is used for the following)

Maintain two arrays, $g {i, j} $indicates the subscript with the largest subscript and the first $j $bit of the number with subscript less than $i $. $f {i, j} $indicates that the subscript of a number whose subscript is less than $i $is the largest, the $j $bit is 1, and the subscript of $i $can be reached.

Needless to say, the preprocessing of $g {i, J} $can enumerate a bit of $k $, which means that $a {i $can be reached from $g {i, K} $through the $k $, and the f value of $i $can be directly deduced by using the f value of $g {i, K} $.

When asking, enumerate a bit of $i $, which means that $r $can arrive from $f {r, i} $, while when the $i $bit of $a {L $is 1 and $f {r, i} \ GEQ L $can arrive at $f {r, i} $, so $l $can arrive at $r $. If not for each bit, output fou.

Time complexity $O(n\log^2n+q\log n)$

 1 #include<bits/stdc++.h>
 2 #define Rint register int
 3 using namespace std;
 4 const int N = 300001;
 5 int n, m, f[N][19], g[N][19];
 6 bool a[N][19];
 7 int main(){
 8     scanf("%d%d", &n, &m);
 9     for(Rint i = 1;i <= n;i ++){
10         int x;
11         scanf("%d", &x);
12         for(Rint j = 0;j < 19;j ++)
13             if(x & (1 << j)) a[i][j] = 1;
14     }
15     for(Rint i = 1;i <= n;i ++)
16         for(Rint j = 0;j < 19;j ++)
17             if(a[i - 1][j]) g[i][j] = i - 1;
18             else g[i][j] = g[i - 1][j];
19     for(Rint i = 1;i <= n;i ++)
20         for(Rint j = 0;j < 19;j ++)
21             for(Rint k = 0;k < 19;k ++)
22                 if(a[i][k]){
23                     int x = g[i][k];
24                     f[i][j] = max(f[i][j], f[x][j]);
25                     if(a[x][j]) f[i][j] = max(f[i][j], x);
26                 }
27     while(m --){
28         int l, r;
29         bool ans = false;
30         scanf("%d%d", &l, &r);
31         for(Rint i = 0;i < 19 && !ans;i ++)
32             if(a[l][i] && f[r][i] >= l) ans = true;
33         puts(ans ? "Shi" : "Fou");
34     }
35 }
CF1168C

Topics: PHP less