[Luogu P3293] [BZOJ 4571] [SCOI2016]美味

版权声明:欢迎转载蒟蒻博客,但请注明出处: https://blog.csdn.net/LPA20020220/article/details/82936240

洛谷传送门

BZOJ传送门

题目描述

一家餐厅有 n n 道菜,编号 1... n 1...n ,大家对第 i i 道菜的评价值为 a i ( 1 i n ) a_i(1\le i\le n) 。有 m m 位顾客,第 i i 位顾客的期望值为 b i b_i ,而他的偏好值为 x i x_i 。因此,第 i i 位顾客认为第 j j 道菜的美味度为 b i   X O R   ( a j + x i ) b_i\ XOR\ (a_j+x_i) X O R XOR 表示异或运算。

i i 位顾客希望从这些菜中挑出他认为最美味的菜,即美味值最大的菜,但由于价格等因素,他只能从第 l i l_i 道到第 r i r_i 道中选择。请你帮助他们找出最美味的菜。

输入输出格式

输入格式:

1 1 行,两个整数, n n m m ,表示菜品数和顾客数。

2 2 行, n n 个整数, a 1 a_1 a 2 a_2 ,…, a n a_n ,表示每道菜的评价值。

3 3 m + 2 m+2 行,每行 4 4 个整数, b b x x l l r r ,表示该位顾客的期望值,偏好值,和可以选择菜品区间。

输出格式:

输出 m m 行,每行 1 1 个整数, y m a x y_{max} ,表示该位顾客选择的最美味的菜的美味值。

输入输出样例

输入样例#1:

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

输出样例#1:

9 
7 
6 
7

说明

对于所有测试数据, 1 n 2 1 0 5 1\le n\le 2*10^5 0 a i , b i , x i 1 0 5 0\le a_i,b_i,x_i<10^5 1 l i r i n ( 1 i m ) 1\le l_i\le r_i\le n(1\le i\le m) 1 m 1 0 5 1\le m\le 10^5

解题分析

这道题相当于这一道题加上一个偏移量 x x , 再按位贪心。

因为有了这个偏移量, 我们没法单纯地在 T r i e Trie 树上跳(因为可能存在进位的情况), 只好掏出主席树, 每次查询的时候查询对应序列区间是否有权值在 [ l b , r b ] [lb,rb] 之间的值, 然后再按位贪心即可。
总复杂度 O ( N l o g 2 ( N ) ) O(Nlog^2(N))

代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstdlib>
#define R register
#define W while
#define IN inline
#define gc getchar()
#define MX 200500
template <class T>
IN void in(T &x)
{
	x = 0; R char c = gc;
	for (; !isdigit(c); c = gc);
	for (;  isdigit(c); c = gc)
	x = (x << 1) + (x << 3) + c - 48;
}
int n, m, cnt, root[MX];
struct Node {int son[2], sum;} tree[MX << 5];
namespace PT
{
	#define ls tree[now].son[0]
	#define rs tree[now].son[1]
	#define pls tree[pre].son[0]
	#define prs tree[pre].son[1]
	void insert(int &now, R int pre, R int lef, R int rig, R int pos)
	{
		now = ++cnt; tree[now] = tree[pre]; tree[now].sum++;
		if(lef == rig) return;
		int mid = lef + rig >> 1;
		if(pos <= mid) insert(ls, pls, lef, mid, pos);
		else insert(rs, prs, mid + 1, rig, pos);
	}
	int query (R int now, R int pre, R int lef, R int rig, R int lb, R int rb)
	{
		if(lef >= lb && rig <= rb) return tree[now].sum - tree[pre].sum;
		int mid = lef + rig >> 1, ret = 0;
		if(lb <= mid) ret += query(ls, pls, lef, mid, lb, rb);
		if(rb  > mid) ret += query(rs, prs, mid + 1, rig, lb, rb);
		return ret;
	}
	#undef ls
	#undef rs
	#undef pls
	#undef prs
}
int main(void)
{
	int b, x, l, r, ans, typ, lb, rb;
	in(n), in(m);
	for (R int i = 1; i <= n; ++i)
	in(b), PT::insert(root[i], root[i - 1], 0, 200000, b);
	for (R int i = 1; i <= m; ++i)
	{
		in(b), in(x), in(l), in(r); ans = 0;
		for (R int digit = 18; ~digit; --digit)
		{
			if(b & (1 << digit)) lb = ans, rb = ans + (1 << digit) - 1, typ = 0;
			else lb = ans + (1 << digit), rb = ans + (1 << digit + 1) - 1, typ = 1;
			if(!PT::query(root[r], root[l - 1], 0, 200000, std::max(lb - x, 0), std::min(rb - x, 200000))) typ ^= 1;
			ans += typ << digit;
		}
		printf("%d\n", ans ^ b);
	}
}

猜你喜欢

转载自blog.csdn.net/LPA20020220/article/details/82936240