help
  • 板块学术版
  • 楼主HourSkit
  • 当前回复1
  • 已保存回复1
  • 发布时间2024/11/8 16:11
  • 上次更新2024/11/8 16:22:28
查看原帖
help
380634
HourSkit楼主2024/11/8 16:11

problem:

https://codeforces.com/gym/103102/problem/H

std:

假设最后两个集合的值均为 val,k 为val 二进制下 1的个数。
容易发现与集合内所有数的二进制下 1的个数大于等于 k,或集合内所有数的二进制下 1的个数小于等
于 k。
枚举 k,钦定二进制下 1的个数小于 k的都用或操作,大于k 的都用与操作,若等于k 的数有多个不同
的则一定无解,否则等于 k的数可以任意选择加入哪个集合中。
每一位开一颗线段树维护即可

pro:

#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;
}
2024/11/8 16:11
加载中...