747 字
4 分钟
[BZOJ3166]: [Heoi2013] Alo

Description#

Welcome to ALO ( Arithmetic and Logistic Online)。这是一个VR MMORPG , 如名字所见,到处充满了数学的谜题。 现在你拥有n颗宝石,每颗宝石有一个能量密度,记为ai,这些宝石的能量 密度两两不同。现在你可以选取连续的一些宝石(必须多于一个)进行融合,设为 ai, ai+1, …, a j,则融合而成的宝石的能量密度为这些宝石中能量密度的次大值

与其他任意一颗宝石的能量密度按位异或的值,即,设该段宝石能量密度次大值 为k,则生成的宝石的能量密度为max{k xor ap | ap ≠ k , i ≤ p ≤ j}。 现在你需要知道你怎么选取需要融合的宝石,才能使生成的宝石能量密度最大。

Input#

第一行,一个整数 n,表示宝石个数。 第二行, n个整数,分别表示a1至an,表示每颗宝石的能量密度,保证对于i ≠ j有 ai ≠ aj。

Output#

输出一行一个整数,表示最大能生成的宝石能量密度。

Sample Input#

5
9 2 1 4 7

Sample Output#

14

HINT#

【样例解释】 选择区间[1,5],最大值为 7 xor 9。 对于 100%的数据有 1 ≤ n ≤ 50000, 0 ≤ ai ≤ 10^9

题解#

如图由左右比他大的值得到了一个区间 1181169-20170803204801365-12244565356d7b7.png

我们用Set维护查排名比他大1的就可以了

#include <cstdio>
#include <set>
#include <algorithm>
int n;
const int INF = 1000000000;
const int full = 30;
struct Trie
{
	struct Trie_Node
	{
		Trie_Node *ch[2];
		int s;
		Trie_Node()
		{
			ch[0] = ch[1] = NULL;
			s = 0;
		}
	} * root[100005], *null;
	Trie()
	{
		null = new Trie_Node();
		null->ch[0] = null->ch[1] = null;
		root[0] = new Trie_Node();
		root[0]->ch[1] = root[0]->ch[0] = null;
	}
	Trie_Node *NewNode()
	{
		Trie_Node *rt = new Trie_Node();
		rt->ch[0] = rt->ch[1] = null;
		return rt;
	}
	void copy(Trie_Node *&a, Trie_Node *b)
	{
		if (b == null)
			a = null;
		else
			a = NewNode(), *a = *b;
	}
	void Insert(int x, int cnt)
	{
		copy(root[cnt], root[cnt - 1]);
		Trie_Node *rt1 = root[cnt], *rt2 = root[cnt - 1];
		for (int i = full; i >= 0; i--)
		{
			int k = (x >> i) & 1;
			copy(rt1->ch[k], rt2->ch[k]);
			if (rt1->ch[k] == null)
				rt1->ch[k] = NewNode();
			rt1 = rt1->ch[k], rt2 = rt2->ch[k];
			rt1->s++;
		}
	}
	int Query(int val, int l, int r)
	{
		int res = 0;
		Trie_Node *rt1 = root[r], *rt2 = root[l - 1];
		for (int i = full; i >= 0; i--)
		{
			int next = (val >> i) & 1;
			if (rt1->ch[next ^ 1]->s - rt2->ch[next ^ 1]->s)
			{
				rt1 = rt1->ch[next ^ 1], rt2 = rt2->ch[next ^ 1];
				res |= (1 << i);
			}
			else
			{
				rt1 = rt1->ch[next], rt2 = rt2->ch[next];
			}
		}
		return res;
	}
} root;
struct data
{
	int val, i;
	bool operator < (const data &a)const 
	{
		return val > a.val;
	}
} a[50005];
std::set<int> st;
int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &a[i].val);
		a[i].i = i;
	}
	for (int i = 1; i <= n; ++i)
	{
		root.Insert(a[i].val, i);
	}
	st.insert(-1), st.insert(INF), st.insert(-2), st.insert(INF + 1);
	std::sort(a + 1, a + n + 1);
	st.insert(a[1].i);
	int ans = 0;
	for (int i = 2; i <= n; i++)
	{
		int l = a[i].i, r = a[i].i;
		std::set<int>::iterator T, P;
		P = st.lower_bound(a[i].i);
		T = P;
		r = *T; T++; r = *T - 1;
		l = *--P; P--;l = *P + 1;
		l = std::max(1, l), r = std::min(r, n);
		if (l != r)
		{
			ans = std::max(ans, root.Query(a[i].val, l, r));
		}
		st.insert(a[i].i);
	}
	printf("%d", ans);
}

[BZOJ3166]: [Heoi2013] Alo
https://www.nekomio.com/posts/66/
作者
NekoMio
发布于
2017-08-05
许可协议
CC BY-NC-SA 4.0