1. 程式人生 > >[bzoj4571][主席樹]美味

[bzoj4571][主席樹]美味

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

題解

好題啊.. 如果沒有加的操作就是個裸的01Tire 有加的怎麼辦.. 考慮到01Tire其實也就是一個簡單的主席樹 設ans=xiajans能使得

bixorans最大 從高到低位貪心,設列舉到了第i位 如果第i位是1,於是要求ans+(1<<i)~ans+(1<<i)+(1<<i)1這個區間裡有數 主席樹搞一搞就行了..

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define MX 100005
using namespace std; struct trnode{int lc,rc,c;}tr[20*200005];int len,rt[200005]; void add(int &now,int l,int r,int p) { if(now==0)now=++len; tr[now].c++; if(l==r)return ; int mid=(l+r)/2; if(p<=mid)add(tr[now].lc,l,mid,p); else add(tr[now].rc,mid+1,r,p); } void meg(int &x,int y) { if(x==0){x=y;return ;} if(y==0)return ; tr[x].c+=tr[y].c; meg(tr[x].lc,tr[y].lc); meg(tr[x].rc,tr[y].rc); } int findsum(int u,int v,int l,int r,int p) { if(p<0)return 0; if(tr[u].c-tr[v].c==0)return 0; if(l==r)return tr[u].c-tr[v].c; int mid=(l+r)/2; if(p<=mid)return findsum(tr[u].lc,tr[v].lc,l,mid,p); else return tr[tr[u].lc].c-tr[tr[v].lc].c+findsum(tr[u].rc,tr[v].rc,mid+1,r,p); } int n,m,a[210000],b[210000],L[210000],R[210000],bin[25]; int main() { bin[0]=1;for(int i=1;i<=20;i++)bin[i]=bin[i-1]<<1; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { int x;scanf("%d",&x); add(rt[i],0,MX,x);meg(rt[i],rt[i-1]); } for(int i=1;i<=m;i++)scanf("%d%d%d%d",&a[i],&b[i],&L[i],&R[i]); for(int i=1;i<=m;i++) { int ans=0; for(int j=20;j>=0;j--) { int col=a[i]&bin[j]; int nw=(col!=0?0:bin[j]),nxt=bin[j]-1; int s1=findsum(rt[R[i]],rt[L[i]-1],0,MX,ans+nw+nxt-b[i]),s2=findsum(rt[R[i]],rt[L[i]-1],0,MX,ans+nw-1-b[i]); if(s1-s2)ans+=nw; else ans+=col; } printf("%d\n",a[i]^ans); } return 0; }