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
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
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 }