首页 > 其他 > 详细

P3293 [SCOI2016]美味 最大异或值 主席树

时间:2019-09-12 17:13:16      阅读:78      评论:0      收藏:0      [点我收藏+]

  技术分享图片

 

 

可以先简化一下问题  看作是给你一个b  问再区间l r 内的数与之异或的最大值 

 

显然是从最高位到最低位开始贪心

技术分享图片

 

 

 

主席树负责查询区间内是否有这个数

技术分享图片
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<‘=‘<<(x)<<endl)
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=2e5+10;
int T[N],t[N<<5],lson[N<<5],rson[N<<5],ncnt;

void upnode(int x,int l,int r,int pre,int &pos)
{    
    pos=++ncnt;
    t[pos]=t[pre]+1;lson[pos]=lson[pre];rson[pos]=rson[pre];
    if(l==r)return ;int m=(l+r)>>1;
    if(x<=m)upnode(x,l,m,lson[pre],lson[pos]);
    else upnode(x,m+1,r,rson[pre],rson[pos]);
}
int qsum(int L,int R,int l,int r,int pre,int pos)
{    
    if(l>r||L>R)return 0;
    if(L<=l&&r<=R)return t[pos]-t[pre];
    int ans=0,m=l+r>>1;
    if(L<=m)ans+=qsum(L,R,l,m,lson[pre],lson[pos]);
    if(R>m)ans+=qsum(L,R,m+1,r,rson[pre],rson[pos]);
    return ans;
}
int a[N],n,m;
int main()
{
    scanf("%d%d",&n,&m);int maxx=0;
    rep(i,1,n)
    scanf("%d",&a[i]),maxx=max(maxx,a[i]);
    rep(i,1,n)
    upnode(a[i],0,maxx,T[i-1],T[i]);
    int b,x,l,r;
    while(m--)
    {
        int ans=0;
        scanf("%d%d%d%d",&b,&x,&l,&r);
        repp(i,23,0)
        {
            int c=(b>>i)&1;
            if(c&&!qsum(ans-x,ans-x+(1<<i)-1,0,maxx,T[l-1],T[r]))ans+=(1<<i);
            else if(!c&&qsum(ans-x+(1<<i),ans-x+(1<<i)+(1<<i)-1,0,maxx,T[l-1],T[r]))ans+=(1<<i);
        }
        printf("%d\n",ans^b);
    }
    return 0;
}
View Code

 

P3293 [SCOI2016]美味 最大异或值 主席树

原文:https://www.cnblogs.com/bxd123/p/11512502.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!