题意:
现在有n个数,如果第a[i]&a[j]>0&&i<j,那么位置i就可以跳到位置j,现在每次都问你第x位到第y个位置中能否找到一个序列使得可以从位置x跳到位置y。
题解:
对于这道题目,我们需要知道每一个位置的每一位可以到达哪里,那么
dp[i][j]表示距离位置i最近的可到达的存在1<<j这一位的位置最大是多少。
而不是最前面,因为如果知道了最后能到哪的话,前面拥有第i位的地方就可以以那一位为跳板跳过来。
那么当前位置拥有的位数能够到达的最后的地方就是这个位置,对于其它位,我们枚举拥有的位,看这个位能够跳的前面的地方所拥有的最后的含有当前没有的位的位置(有点绕)美也就是状态转移。
那么对于输入的x,y如果当前位x有并且y能够到达的地方>=x,说明x能够通过dp[y][i]跳过来。
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
int dp[N][25],pos[25],a[N];
int main()
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
for(int j=0;j<=20;j++){
if(a[i]&(1<<j))
dp[i][j]=i;
else{
for(int k=0;k<=20;k++)
if(a[i]&(1<<k))
dp[i][j]=max(dp[i][j],dp[pos[k]][j]);
}
}
for(int j=0;j<=20;j++)
if(a[i]&(1<<j))
pos[j]=i;
}
while(q--){
int x,y;
scanf("%d%d",&x,&y);
int f=0;
for(int i=0;i<=20;i++)
if(a[x]&(1<<i)&&dp[y][i]>=x)
f=1;
printf("%s\n",f?"Shi":"Fou");
}
return 0;
}