https://codeforces.com/gym/103102/problem/H
假设最后两个集合的值均为 val,k 为val 二进制下 1的个数。
容易发现与集合内所有数的二进制下 1的个数大于等于 k,或集合内所有数的二进制下 1的个数小于等
于 k。
枚举 k,钦定二进制下 1的个数小于 k的都用或操作,大于k 的都用与操作,若等于k 的数有多个不同
的则一定无解,否则等于 k的数可以任意选择加入哪个集合中。
每一位开一颗线段树维护即可
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
int n,q;
int a[MAXN];
int vis[MAXN]={0};//二进制下1的个数
//2的30次方=1073741824
#define qw 1073741824
struct tree//线段树
{
int l,r;
int _and=-1,_or=-1;
int s1,s2;
int tag=-1;//二进制下1的个数=k的数
bool leg=false;//是否合法
}t[MAXN<<2][32];
struct ret
{
int _and=-1,_or=-1;
int s1,s2;
};
void build(int p,int l,int r,int k)//建树
{
#define ls p<<1
#define rs p<<1|1
#define tp t[p][k]
tp.l=l,tp.r=r;
if(l==r)
{
if(vis[l]==k) tp.tag=a[l],tp.s1=tp.s2=0;
else if(vis[l]>k) tp._or=a[l],tp.s1=1,tp.s2=0;
else tp._and=a[l],tp.s1=0,tp.s2=1;
}
else
{
int mid=(l+r)>>1;
build(ls,l,mid,k);
build(rs,mid+1,r,k);
if(t[ls][k].tag==-1&&t[rs][k].tag==-1) tp.leg=false;
else if(t[ls][k].tag!=-1||t[rs][k].tag!=-1)
tp.tag=t[ls][k].tag!=-1?t[ls][k].tag:t[rs][k].tag;
tp._and=t[ls][k]._and&t[rs][k]._and;
tp._or=t[ls][k]._or|t[rs][k]._or;
tp.s1=t[ls][k].s1+t[rs][k].s1;
tp.s2=t[ls][k].s2+t[rs][k].s2;
if(t[ls][k].tag!=-1&&t[rs][k].tag!=-1)
tp.leg=tp._and==tp._or;
}
}
ret query(int p,int l,int r,int k)//查询,返回所得的and和or
{
#define tp t[p][k]
#define ls p<<1
#define rs p<<1|1
#define pl tp.l
#define pr tp.r
if(l<pr||r>pl)
{
ret q;q._and=qw,q._or=0;q.s1=q.s2=0;
return q;
}
if(l>=pl&&r<=pr)
{
ret q;q._and=tp._and,q._or=tp._or;
q.s1=tp.s1,q.s2=tp.s2;
return q;
}
else
{
ret q1=query(ls,l,r,k),q2=query(rs,l,r,k);
ret q;q._and=q1._and&q2._and,q._or=q1._or|q2._or;
q.s1=q1.s1+q2.s1,q.s2=q1.s2+q2.s2;
return q;
}
}
int read()//快读
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
signed main()
{
n=read(),q=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
int p=a[i],t=0;
while(p)
{
vis[i]+=p&1,p>>=1,t++;
}
}
for(int k=1;k<=30;k++) build(1,1,n,k);
for(int i=1;i<=q;i++)
{
int l=read(),r=read();
bool check=false;
for(int k=1;k<=30;k++)
{
ret q=query(1,l,r,k);
check|=(q._and==q._or&&q.s1&&q.s2);
if(check) break;
}
if(check) printf("YES\n");
else printf("NO\n");
}
return 0;
}