[Scoi 2016] 美味

题目描述:

给出 N 个 A
给出 Q 个 询问
每个询问有四个量 分别为 B,X,L,R
每个A 的价值为 B xor (X+Ai)(l<=i<=r) B   x o r   ( X + A i ) ( l <= i <= r )
求出最大的价值

题目分析:

如果没有那个 X 的 干扰 ,那我们就可以用可持久化Tire树搞一下

同样是按照数位一位一位的贪心,因为加了一个x,所以我们考虑对于所有的ai+x与b的按位异或。

假设我们已经处理到b的第i位(转换成二进制),假设是1(0同理),

那么我们只需要查找是否存在aj+x使得其二进制第i位数字是0,显然我们已经处理了前i-1位了,设当前结果是ans,那么我们需要查找的数的大小就是在区间 [ansx,ans+(1<<i)1x] [ a n s − x , a n s + ( 1 << i ) − 1 − x ] ,手算一下就知道这个区间里的数字的第i位加了x后就都是0,

那么现在我们就是要在a[1]…a[n]中找出是否存在于 [ansx,ans+(1<<i)1x] [ a n s − x , a n s + ( 1 << i ) − 1 − x ] 的数字,两个区间范围限制,用主席树模板一套就好了。

由于多了个查询范围,比朴素的主席树维护的方法多了个log 不过还是受得起的

题目链接:

Luogu 3293
BZOJ 4571

AC 代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
const int maxm=4000005;
const int N=2*1e5+100;
int lson[maxm],rson[maxm],sum[maxm];
int rt[N],siz,n,q,maxr;
void insert(int &o,int pre,int l,int r,int ind)
{
    o=++siz;
    lson[o]=lson[pre],rson[o]=rson[pre],sum[o]=sum[pre]+1;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(ind<=mid) insert(lson[o],lson[pre],l,mid,ind);
    else insert(rson[o],rson[pre],mid+1,r,ind);
}
int asksum(int o,int pre,int l,int r,int ql,int qr)
{
    //printf("%d %d\n",l,r);
    if(ql<=l&&r<=qr) return sum[o]-sum[pre];
    int mid=(l+r)>>1;
    int sumx=0;
    if(ql<=mid) sumx+=asksum(lson[o],lson[pre],l,mid,ql,qr);
    if(qr>mid) sumx+=asksum(rson[o],rson[pre],mid+1,r,ql,qr);
    return sumx;
}
int main()
{
    maxr=262144;
    scanf("%d%d",&n,&q);
    for(int i=1,x;i<=n;i++) scanf("%d",&x),insert(rt[i],rt[i-1],0,maxr,x);
    while(q--)
    {
        int l,r,x,b;
        int ans=0; 
        scanf("%d%d%d%d",&b,&x,&l,&r);
        l--; 
        for(int i=17;i>=0;i--)
        {
            if(!((b>>i)&1)) ans^=(1<<i);
            int ql=std::max(ans-x,0),qr=ans+(1<<i)-x-1;
            if(qr<0||!asksum(rt[r],rt[l],0,maxr,ql,qr)) ans^=(1<<i);
        }
        printf("%d\n",ans^b);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值