【bzoj4571】[Scoi2016]美味 主席树

题目描述

给出一个长度为n的序列,m询问,每次询问求出[l,r]范围内的每一个数加上x再与b异或能够得到的最大值。

输入

第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

输出

输出 m 行,每行 1 个整数,ymax ,表示该位顾客选择的最美味的菜的美味值。

样例输入

4 4
1 2 3 4
1 4 1 4
2 3 2 3
3 2 3 3
4 1 2 4

样例输出

9
7
6
7


题解

主席树

如果没有+x这个条件显然是可持久化Trie树。

有了这个条件以后不能直接使用可持久化Trie树,但是按位贪心的这个方法仍然可以使用。

考虑每一位,把满足高位的情况下,使得该位为1的a+x的范围拿出来,减去x得到a的范围。如果[l,r]中这个范围内有数,则该位为1;否则该位为0。

这样从高位到地位枚举,每次会将当前区间分成两部分(当前位为0和当前位为1),不断确定区间中数的个数即可出解。

时间复杂度$O(n\log^2 n)$。

(做完本题后可以回想一下01Trie树的实质:权值范围为$[0,2^k)$的权值线段树。权值范围使得每次查询都可以直接判断子树大小以及O(1)移动节点指针,使得查询复杂度变为$O(\log n)$)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 200010
#define M 1000000
#define lson l , mid , ls[x] , ls[y]
#define rson mid + 1 , r , rs[x] , rs[y]
using namespace std;
int ls[N * 30] , rs[N * 30] , si[N * 30] , tot , root[N];
void insert(int p , int l , int r , int x , int &y)
{
	y = ++tot , si[y] = si[x] + 1;
	if(l == r) return;
	int mid = (l + r) >> 1;
	if(p <= mid) rs[y] = rs[x] , insert(p , lson);
	else ls[y] = ls[x] , insert(p , rson);
}
int query(int b , int e , int l , int r , int x , int y)
{
	if(b <= l && r <= e) return si[y] - si[x];
	int mid = (l + r) >> 1 , ans = 0;
	if(b <= mid) ans += query(b , e , lson);
	if(e > mid) ans += query(b , e , rson);
	return ans;
}
int solve(int b , int x , int l , int r)
{
	int i , now = 0 , y , z , ans = 0;
	for(i = 1 << 17 ; i ; i >>= 1)
	{
		if(b & i) y = now , z = now + i - 1;
		else y = now + i , z = now + 2 * i - 1;
		y -= x , z -= x;
		if(query(y , z , -M , M , root[l - 1] , root[r]))
		{
			ans |= i;
			if(!(b & i)) now |= i;
		}
		else if(b & i) now |= i;
	}
	return ans;
}
int main()
{
	int n , m , i , b , x , l , r;
	scanf("%d%d" , &n , &m);
	for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &x) , insert(x , -M , M , root[i - 1] , root[i]);
	for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d%d" , &b , &x , &l , &r) , printf("%d\n" , solve(b , x , l , r));
	return 0;
}

 

posted @ 2017-10-13 14:28  GXZlegend  阅读(370)  评论(0编辑  收藏  举报