AFO

CF1168C

CF1168C

从后往前扫一遍维护\(f[x][k]\)表示从开始x至少要走到那个位置才能到达一个第\(k\)位是1的数

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>

using namespace std;

int n,m,a[310001],w[20][20],e[20],f[310001][20],x,y,d[20];

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	memset(w,0x3f,sizeof(w));
	memset(f,0x3f,sizeof(f));
	for(int i=n;i>=1;i--)
	{
		memset(e,0,sizeof(e)); memset(d,0x3f,sizeof(d)); int ct=0;
		for(int j=0;j<=18;j++) if(a[i]&(1<<j)) e[++ct]=j,w[j][j]=i;
		for(int j=1;j<ct;j++)
			for(int k=j+1;k<=ct;k++) w[e[j]][e[k]]=w[e[k]][e[j]]=i;
		for(int j=0;j<=18;j++)
			for(int k=1;k<=ct;k++) d[j]=min(d[j],w[e[k]][j]);
		for(int j=0;j<=18;j++)
			for(int k=1;k<=ct;k++) w[e[k]][j]=d[j];
		for(int j=1;j<=ct;j++) 
			for(int k=0;k<=18;k++) f[i][k]=min(f[i][k],w[e[j]][k]);
	}
	for(;m;m--)
	{
		scanf("%d%d",&x,&y); int B=0;
		for(int k=0;k<=18;k++) if(a[y]&(1<<k))	if(f[x][k]<=y) B=1;
		if(B) printf("Shi\n");
		else printf("Fou\n");
	}
}
posted @ 2019-09-19 17:18  ZUTTER☮  阅读(113)  评论(0编辑  收藏  举报