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=xi∗ajans=xi∗aj且ansans能使得bixoransbixorans最大
从高到低位贪心,设枚举到了第i位
如果第i位是1,于是要求ans+(1<<i)ans+(1<<i)~ans+(1<<i)+(1<<i)−1ans+(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;
}