Codeforces Round #562 (Div. 1) C. And Reachability
考虑\(dp\),\(dp[i][j]\)表示从i开始最先到达的第j位为1的位置
如果\(a[x]\)能转移到\(a[y]\)那么必定有一位二进制位置上,\(dp[x][k]<=y\)
\(dp\)转移:从\(n\)向\(1\)枚举\(i\),如果\(a[i]\)在某一位上为\(1\),就用上一个该位为1的数更新\(dp[i][j]\).
const int maxn = 3e5 + 7;
int n, t, m;
int a[maxn];
int dp[maxn][30], nex[maxn];
void solve() {
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n + 1; i++)
fill(dp[i], dp[i] + 30, n + 1);
fill(nex, nex + maxn, n + 1);
for (int i = n; i >= 1; i--) {
for (int j = 25; j >= 0; j--) {
if ((a[i] >> j) & 1) {
for (int k = 0; k <= 25; k++)
dp[i][k] = min(dp[i][k], dp[nex[j]][k]);
dp[i][j] = i;
nex[j] = i;
}
}
}
for (int i = 1, x, y; i <= m; i++) {
cin >> x >> y;
int fg = 0;
for (int k = 0; k <= 25; k++)
if ((a[y] >> k) & 1)
fg |= (dp[x][k] <= y);
if (fg) cout << "Shi" << endl;
else cout << "Fou" << endl;
}
}
我看见 你