bzoj4571 [Scoi2016] yummy, greedy and chairman tree

Description

One restaurant has N dishes, number 1 N, the evaluation value of the first course is ai(1 ≤ i ≤ n). Period with m customers and i customers
The expected value is Bi, and his preference value is xi. Therefore, the i-th customer thinks that the delicious degree of the j-th course is bi XOR (aj+xi), XOR means exclusive or
Operation. The ith customer wants to pick out the most delicious dish from these dishes, that is, the dish with the most delicious value. However, due to the price and other factors, he can only choose from the
li channel to ri channel. Please help them find the most delicious food.

1≤n≤2×105,0≤ai,bi,xi<105,1≤li≤ri≤n(1≤i≤m);1≤m≤105

Solution

Notice how annoying this addition is, so we are greedy
If we determine the answer bit ans of the first i-1 bit, for the first I-bit, if we take 0, then [l,r] has a number i n the range of [ans-x, ans + (1 < < n) - X-1]
Why is that so? It can be found that we actually take the remaining i+1 positions after adding 0 to the i-th bit of ans, which is similar to taking 1 for the i-th bit
So this becomes a classical two-dimensional problem, which can be solved by the upper persistent line tree
It's said that there's a magic way to make trie sustainable. It's really hard

Code

#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)

const int INF=100000;
const int N=200005;

struct treeNode {
	int l,r,sum;
} t[N*51];

int root[N],tot;

inline int read() {
	int x=0,v=1; char ch=getchar();
	for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
	for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
	return x*v;
}

void modify(int &now,int pre,int tl,int tr,int x) {
	t[now=++tot]=t[pre]; t[now].sum++;
	if (tl==tr) return ;
	int mid=(tl+tr)>>1;
	if (x<=mid) modify(t[now].l,t[pre].l,tl,mid,x);
	else modify(t[now].r,t[pre].r,mid+1,tr,x);
}

int query(int now,int pre,int tl,int tr,int l,int r) {
	if (!t[now].sum||r<l) return 0;
	if (tl==l&&tr==r) return t[now].sum-t[pre].sum;
	int mid=(tl+tr)>>1;
	if (r<=mid) return query(t[now].l,t[pre].l,tl,mid,l,r);
	if (l>mid) return query(t[now].r,t[pre].r,mid+1,tr,l,r);
	int qx=query(t[now].l,t[pre].l,tl,mid,l,mid);
	int qy=query(t[now].r,t[pre].r,mid+1,tr,mid+1,r);
	return qx+qy;
}

int main(void) {
	int n=read(),m=read();
	rep(i,1,n) {
		int x=read();
		modify(root[i],root[i-1],0,INF,x);
	}
	for (;m--;) {
		int b=read(),x=read(),l=read(),r=read();
		int ans=0;
		drp(i,20,0) if (b&(1<<i)) {
			if (!query(root[r],root[l-1],0,INF,std:: max(ans-x,0),ans+(1<<i)-x-1)) {
				ans^=(1<<i);
			}
		} else {
			ans^=(1<<i);
			if (!query(root[r],root[l-1],0,INF,std:: max(ans-x,0),ans+(1<<i)-1-x)) {
				ans^=(1<<i);
			}
		}
		printf("%d\n", ans^b);
	}
	return 0;
}

Posted by trparky on Mon, 16 Dec 2019 10:09:49 -0800