【bzoj4571 scoi2016】美味

题目描述

一家餐厅有 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 ,表示该位顾客选择的最美味的菜的美味值。

题意:
n个数,m个询问,每个询问要求输出l-r区间内(ai+x) xor b的最大值;

 ①一个数异或多个数异或最大值,还是可以考虑可持久化字典树

②但是有偏好值,让可持久话字典树变成字典树套主席树,构造到第j位,已经确定好的j位以上的答案(ai+x)是ans,每次在ans^(~b&(1<<j)) 到 ans^(~b&(1<<j)) + (1<<j)-1区间里查询是否有值。

 

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 const int N = 200010,S = 20,M = 100000;
 5 int n,m,sz,a[N],rt[N],ls[N*S],rs[N*S],sum[N*S],bin[S];
 6 char gc(){
 7     static char *p1,*p2,s[1000000];
 8     if(p1==p2) p2=(p1=s)+fread(s,1,1000000,stdin);
 9     return(p1==p2)?EOF:*p1++;
10 }
11 int rd(){
12     int x = 0,f = 1; char c = gc();
13     while(c<'0'||c>'9') {if(c=='-') f = -1; c = gc();}
14     while(c>='0'&&c<='9') x=x*10+c-'0',c = gc();
15     return x * f;
16 }
17 void ins(int &k,int last,int l,int r,int x){
18     k = ++sz; 
19     sum[k] = sum[last] + 1,ls[k] = ls[last],rs[k] = rs[last];
20     if(l==r) return ;
21     int mid = (l+r)>>1;
22     if(x<=mid) ins(ls[k],ls[last],l,mid,x);
23     else ins(rs[k],rs[last],mid+1,r,x);
24 }
25 bool query(int k1,int k2,int l,int r,int ql,int qr){
26     if(l==ql&&qr==r){
27         return bool(sum[k2]-sum[k1]);
28     }
29     else {
30         int mid = (l+r)>>1;
31         if(qr<=mid) return query(ls[k1],ls[k2],l,mid,ql,qr);
32         else if(ql>mid) return query(rs[k1],rs[k2],mid+1,r,ql,qr);
33         else return query(ls[k1],ls[k2],l,mid,ql,mid)|query(rs[k1],rs[k2],mid+1,r,mid+1,qr);
34     }
35 }
36 int main()
37 {    freopen("bzoj4571.in","r",stdin);
38     freopen("bzoj4571.out","w",stdout);
39     n  = rd(); m = rd();
40     for(int i = 1;i <= n;i++) ins(rt[i],rt[i-1],0,M,a[i] = rd());
41     for(int i = bin[0] = 1;i <= 17;i++) bin[i] = bin[i-1]<<1;
42     for(int i = 1,l,r,b,x;i <= m;i++){
43         b = rd(); x = rd(); l = rd(); r = rd();
44         int ans = 0;
45         for(int k = 17;k>=0;k--){
46             if(!((b>>k)&1)) ans |= bin[k];
47             int L = max(0,ans - x),R = min((ans|(bin[k]-1)) - x,M); 
48             if(L > M || R < 0 || !query(rt[r],rt[l-1],0,M,L,R)) ans ^= bin[k];
49         }
50         printf("%d\n",ans^b);
51     }
52     return 0;
53 }//by tkys_Austin;

 

 

 

posted @ 2018-03-26 08:00  大米饼  阅读(161)  评论(0编辑  收藏  举报