本文主要是介绍[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=xi∗aj a n s = x i ∗ a j 且 ans a n s 能使得 bixorans b i x o r a n s 最大
从高到低位贪心,设枚举到了第i位
如果第i位是1,于是要求 ans+(1<<i) a n s + ( 1 << i ) ~ ans+(1<<i)+(1<<i)−1 a n s + ( 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;
}
这篇关于[bzoj4571][主席树]美味的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!