博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ4517[Scoi2016]美味——主席树
阅读量:6919 次
发布时间:2019-06-27

本文共 2147 字,大约阅读时间需要 7 分钟。

题目描述

一家餐厅有 n 道菜,编号 1...n ,大家对第 i 道菜的评价值为 ai(1≤i≤n)。有 m 位顾客,第 i 位顾客的期
望值为 bi,而他的偏好值为 xi 。因此,第 i 位顾客认为第 j 道菜的美味度为 bi XOR (aj+xi),XOR 表示异或
运算。第 i 位顾客希望从这些菜中挑出他认为最美味的菜,即美味值最大的菜,但由于价格等因素,他只能从第 
li 道到第 ri 道中选择。请你帮助他们找出最美味的菜。
 

输入

第1行,两个整数,n,m,表示菜品数和顾客数。
第2行,n个整数,a1,a2,...,an,表示每道菜的评价值。
第3至m+2行,每行4个整数,b,x,l,r,表示该位顾客的期望值,偏好值,和可以选择菜品区间。
1≤n≤2×10^5,0≤ai,bi,xi<10^5,1≤li≤ri≤n(1≤i≤m);1≤m≤10^5
 

输出

 输出 m 行,每行 1 个整数,ymax ,表示该位顾客选择的最美味的菜的美味值。

样例输入

4 4
1 2 3 4
1 4 1 4
2 3 2 3
3 2 3 3
4 1 2 4

样例输出

9
7
6
7
 
  一看到位异或第一时间就会想到按位从高到底贪心,这道题也是这样的,但稍有不同的是要两个数的和与另一个数位异或结果最大。还是从高位到低位考虑,如果b当前为是1(0的方法一样),那么希望x+a这一位是0,因为更高位已经确定了,所以满足要求的a+x的值一定是一个区间——假设更高位已经确定的答案是ans(ans的值即为更高位贪心取最优解,其他位都是0),那么a+x的区间就是[ans,ans+(1<<i)-1],把x挪到等号那边就能知道要使这一位异或结果最优所需的a的范围,只要在主席树上查询是否有这个区间内的数,有的话把ans的这一位加上b这一位相反的数。因为得到的ans是a+x的值,所以最后还要ans^=b。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;int n,m;int l,r;int cnt;int ans;int maxv;int a,b,x;int ls[4000010];int rs[4000010];int sum[4000010];int root[200010];int updata(int pre,int l,int r,int v){ int rt=++cnt; if(l==r) { sum[rt]=sum[pre]+1; return rt; } ls[rt]=ls[pre]; rs[rt]=rs[pre]; sum[rt]=sum[pre]+1; int mid=(l+r)>>1; if(v<=mid) { ls[rt]=updata(ls[pre],l,mid,v); } else { rs[rt]=updata(rs[pre],mid+1,r,v); } return rt;}int query(int x,int y,int l,int r,int L,int R){ if(L<=l&&r<=R) { return sum[y]-sum[x]; } int mid=(l+r)>>1; if(L>mid) { return query(rs[x],rs[y],mid+1,r,L,R); } else if(R<=mid) { return query(ls[x],ls[y],l,mid,L,R); } else { return query(ls[x],ls[y],l,mid,L,R)+query(rs[x],rs[y],mid+1,r,L,R); }}bool find(int l,int r,int L,int R){ L=max(0,L); R=min(maxv,R); if(L>R) { return 0; } else { return query(root[l],root[r],0,1<<18,L,R); }}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a); maxv=max(a,maxv); root[i]=updata(root[i-1],0,1<<18,a); } for(int j=1;j<=m;j++) { scanf("%d%d%d%d",&b,&x,&l,&r); ans=0; for(int i=17;i>=0;i--) { int now=ans+((((b>>i)&1)^1)<
>i)&1)<

转载于:https://www.cnblogs.com/Khada-Jhin/p/9449376.html

你可能感兴趣的文章
hibernateTemplate类的使用-总结
查看>>
PHP生成随机的HTML颜色代码
查看>>
python最简单的发邮件方式(不带附件)
查看>>
maven第二节-maven基础-依赖管理
查看>>
通过脚本加hosts.deny文件阻止防***
查看>>
javascript函数的3种定义方式
查看>>
ORA-12578: TNS:wallet open failed
查看>>
快收藏!高手Linux运维管理必备工具大全,你会吗?
查看>>
Linux下Redis服务安全加固
查看>>
我的友情链接
查看>>
Dockerfile构建简单的mysql
查看>>
nutch介绍和安装配置
查看>>
Linux下的tar压缩解压缩命令详解
查看>>
JDK环境变量配置
查看>>
AKKA入门
查看>>
如何使用KeyChain保存和获取UDID
查看>>
理解css中的长度单位
查看>>
折半算法的demo
查看>>
windows && linux 访问github
查看>>
【JavaScript】容器尺寸/偏移尺寸/滚动条距离
查看>>