【bzoj4571】美味

Portal -->bzoj4571

Solution

  emmm持续智力康复。。

  虽然说因为统计的是加上\(x\)的跟\(b\)异或的最大值所以可持久化trie用不了了

​  但是按位贪心的思想还是非常ok的

  然后又因为权值范围比较小,那就权值线段树然后可持久化一下,对于一个查询\(b\),我们从高位到低位枚举每一位,对于当前枚举到的第\(j\)位,先确定一个范围,这个范围内的任意一个数\(i\)加上\(x\)后都满足\(i\)^\(b\)的结果的第\(j\)位为1,然后我们在这个范围内的主席树上查一下有没有在这个区间内的数,有的话就说明这位可以满足异或后为\(1\),搞到答案里面去,否则就不能为\(1\),不管,然后接着枚举下一位,总的复杂度\(O(nlog^2n)\)

  (其实就是。。把按位贪心的过程从trie上面搬到了主席树上。。)

​   

​  代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=2*(1e5)+10,SEG=N*20,MX=N,TOP=20;
int a[N];
int n,m,mx,L,R;
namespace Seg{/*{{{*/
    int ch[SEG][2],sum[SEG],rt[N];
    int n,tot;
    void init(int _n){n=_n; tot=0;}
    int newnode(int pre){
        ch[++tot][0]=ch[pre][0]; ch[tot][1]=ch[pre][1]; sum[tot]=sum[pre];
        return tot;
    }
    void _insert(int pre,int &x,int d,int lx,int rx){
        x=newnode(pre);
        ++sum[x];
        if (lx==rx) return;
        int mid=lx+rx>>1;
        if (d<=mid) _insert(ch[pre][0],ch[x][0],d,lx,mid);
        else _insert(ch[pre][1],ch[x][1],d,mid+1,rx);
    }
    void insert(int pre,int x,int d){_insert(rt[pre],rt[x],d,1,n);}
    bool _query(int L,int R,int l,int r,int lx,int rx){
        if (!R) return 0;
        if (l<=lx&&rx<=r) return (sum[R]-sum[L])>0;
        int mid=lx+rx>>1,ret=0;
        if (l<=mid) ret|=_query(ch[L][0],ch[R][0],l,r,lx,mid);
        if (r>mid) ret|=_query(ch[L][1],ch[R][1],l,r,mid+1,rx);
        return ret;
    }
    bool query(int tL,int tR,int l,int r){return _query(rt[tL-1],rt[tR],l,r,1,n);}
}/*}}}*/

int main(){
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
#endif
    int b,x,l,r,tmp;
    scanf("%d%d",&n,&m);
    Seg::init(MX);
    for (int i=1;i<=n;++i){
        scanf("%d",a+i);
        Seg::insert(i-1,i,a[i]);
    }
    for (int i=1;i<=m;++i){
        scanf("%d%d%d%d",&b,&x,&l,&r);
        tmp=0;
        for (int j=TOP;j>=0;--j){
            if (b>>j&1){
                L=max(0,tmp-x); R=(tmp|((1<<j)-1))-x;
                if (R<0||!Seg::query(l,r,L,R)) tmp^=(1<<j);
            }
            else{
                L=max(0,(tmp^(1<<j))-x); R=((tmp^(1<<j))|((1<<j)-1))-x;
                if (R<0||!Seg::query(l,r,L,R)) continue;
                else tmp^=(1<<j);
            }
        }
        printf("%d\n",tmp^b);
    }
}

猜你喜欢

转载自www.cnblogs.com/yoyoball/p/9395931.html