bzoj4571 [Scoi2016]美味

Description

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

Input

第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

Output

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

Sample Input

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

Sample Output

9
7
6
7

正解:主席树。

其实并不难,应该想得出的,但是我真的好蠢。。可能今天状态不好吧。。

如果没有加数,那么就是裸的可持久化trie树,但是有一个加法,那么trie树就是乱搞了。

我们从高到低考虑每一位能否取最优值。设j是当前位,如果j这位能取的话,那么当前的期望ans就是[ans,(ans|((1<<j)-1))](这个要仔细想想才能想通),ans的下界就是更高位上已经得到的ans再加上这一位的期望(0 or 1)。只要找ans-x到(ans|((1<<j)-1))-x上有没有数。那么我们就直接在主席树上找这个区间有没有数就行了。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <complex>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (1<<30)
15 #define NN (262144)
16 #define N (200010)
17 #define il inline
18 #define RG register
19 #define ll long long
20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
21 
22 using namespace std;
23 
24 int sum[20*N],ls[20*N],rs[20*N],rt[N],a[N],n,m,sz,ans;
25 
26 il int gi(){
27     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
28     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
29 }
30 
31 il void insert(RG int x,RG int &y,RG int l,RG int r,RG int v){
32     sum[y=++sz]=sum[x]+1,ls[y]=ls[x],rs[y]=rs[x]; if (l==r) return; RG int mid=(l+r)>>1;
33     v<=mid ? insert(ls[x],ls[y],l,mid,v) : insert(rs[x],rs[y],mid+1,r,v);
34 }
35 
36 il int query(RG int x,RG int y,RG int l,RG int r,RG int xl,RG int xr){
37     if (xl<=l && r<=xr) return sum[y]-sum[x]>0; RG int mid=(l+r)>>1;
38     if (xr<=mid) return query(ls[x],ls[y],l,mid,xl,xr);
39     else if (xl>mid) return query(rs[x],rs[y],mid+1,r,xl,xr);
40     else return query(ls[x],ls[y],l,mid,xl,mid)|query(rs[x],rs[y],mid+1,r,mid+1,xr);
41 }
42 
43 il void work(){
44     n=gi(),m=gi();
45     for (RG int i=1;i<=n;++i) a[i]=gi(),insert(rt[i-1],rt[i],0,NN,a[i]);
46     for (RG int i=1;i<=m;++i){
47     RG int b=gi(),x=gi(),l=gi(),r=gi(); ans=0;
48     for (RG int j=17;j>=0;--j){
49         if (!(b&(1<<j))) ans^=1<<j;
50         RG int L=max(ans-x,0),R=(ans|((1<<j)-1))-x;
51         if (R<0 || !query(rt[l-1],rt[r],0,NN,L,R)) ans^=1<<j;
52     }
53     printf("%d\n",ans^b);
54     }
55     return;
56 }
57 
58 int main(){
59     File("delicious");
60     work();
61     return 0;
62 }

 

posted @ 2017-03-01 17:37  wfj_2048  阅读(633)  评论(3编辑  收藏  举报