P3293 [SCOI2016]美味 主席树+按位贪心

给定长度为 (n) 序列 (a[i]) ,每次询问区间 ([l,r]) ,并给定 (b,x) 中的一个数 (p=a[i]) ,使得最大化 (b igoplus p^x)

主席树+按位贪心。
我们可以直接贪每一位长什么样子,然后再主席树上区间查询即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
	register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
	do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=200010,B=17;
int n,m,L,tot,a[N];
int sum[N*20],ls[N*20],rs[N*20],rt[N];
inline void ins(int& tr,int t,int l,int r,int p) {
	tr=++tot; sum[tr]=sum[t]+1,ls[tr]=ls[t],rs[tr]=rs[t];
	if(l==r) return ; R md=l+r>>1;
	p<=md?ins(ls[tr],ls[t],l,md,p):ins(rs[tr],rs[t],md+1,r,p);
}
inline bool query(int tr,int t,int l,int r,int LL,int RR) {
	if(r<LL||l>RR||sum[tr]-sum[t]<=0) return 0;
	if(l==r) return sum[tr]-sum[t];
	R md=l+r>>1;
	return (LL<=md&&ls[tr]&&query(ls[tr],ls[t],l,md,LL,RR))
				||(RR>md&&rs[tr]&&query(rs[tr],rs[t],md+1,r,LL,RR));
}
inline void main() {
	n=g(),m=g();
	for(R i=1;i<=n;++i) a[i]=g(),L=max(L,a[i]);
	for(R i=1;i<=n;++i) ins(rt[i],rt[i-1],0,L,a[i]);
	for(R i=1,b,x,l,r,ans;i<=m;++i) { ans=0;
		b=g(),x=g(),l=g(),r=g();
		for(R t=B;~t;--t) {
			if((b>>t&1)&&!query(rt[r],rt[l-1],0,L,ans-x,ans+(1<<t)-1-x)) ans+=1<<t;
			if(!(b>>t&1)&&query(rt[r],rt[l-1],0,L,ans+(1<<t)-x,ans+(1<<t+1)-1-x)) ans+=1<<t;
		} printf("%d
",b^ans);
	}
}
} signed main() {Luitaryi::main(); return 0;}

2019.11.23

原文地址:https://www.cnblogs.com/Jackpei/p/11919861.html