【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×105,0≤ai,bi,xi<105,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

题解

真题真的好诶。。。
如果是一个啥东西\(xor\ ai\)应该还是很好做的
直接搭一个可持久化Trie树就行了
但是,现在是\(b\ xor \ ai\)
我们按照位来考虑,
如果当前是第\(l\)
那么,如果能够贪心的匹配上一个1的话
显然,那就在一个范围内需要存在\(ai\)的值
因此,对于\(ai\)搭值域线段树
每次查询区间内是否存在\(ai\)的值
如果存在,本次贪心有效
否则无效
最后就很简单了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 500000
inline int read()
{
	int x=0,t=1;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=-1,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return x*t;
}
struct Node
{
	int ls,rs;
	int v;
}t[MAX<<5];
int tot,rt[MAX],N=200005;
int B,X,L,R;
int n,m,a[MAX];
void Build(int &now,int l,int r)
{
	now=++tot;
	if(l==r)return;
	int mid=(l+r)>>1;
	Build(t[now].ls,l,mid);
	Build(t[now].rs,mid+1,r);
}
void Modify(int &now,int ff,int l,int r,int pos)
{
	now=++tot;t[now]=t[ff];t[now].v++;
	if(l==r)return;
	int mid=(l+r)>>1;
	if(pos<=mid)Modify(t[now].ls,t[ff].ls,l,mid,pos);
	else Modify(t[now].rs,t[ff].rs,mid+1,r,pos);
}
int Query(int A,int B,int l,int r,int al,int ar)
{
	if(al<=l&&r<=ar)return t[A].v-t[B].v;
	int mid=(l+r)>>1,ret=0;
	if(al<=mid)ret+=Query(t[A].ls,t[B].ls,l,mid,al,ar);
	if(ar>mid)ret+=Query(t[A].rs,t[B].rs,mid+1,r,al,ar);
	return ret;
}
int main()
{
	n=read();m=read();
	for(int i=1;i<=n;++i)a[i]=read();
	Build(rt[0],0,N);
	for(int i=1;i<=n;++i)Modify(rt[i],rt[i-1],0,N,a[i]);
	while(m--)
	{
		B=read();X=read();L=read();R=read();
		int ans=0;
		int ll,rr;
		for(int i=17,g;i>=0;--i)
		{
			if(B&(1<<i))ll=ans,rr=ans+(1<<i)-1,g=0;
			else ll=ans+(1<<i),rr=ans+(1<<(i+1))-1,g=1;
			if(!Query(rt[R],rt[L-1],0,N,max(0,ll-X),min(N,rr-X)))g^=1;
			ans+=g<<i;
		}
		printf("%d\n",ans^B);
	}
}

posted @ 2017-12-30 11:27  小蒟蒻yyb  阅读(274)  评论(1编辑  收藏  举报