【可持久化Trie】【set】bzoj3166 [Heoi2013]Alo

枚举每个数,计算以其为次大数的最大区间,显然,只需要用这个区间的答案 对 答案进行更新即可。

找到每个数右侧、左侧第1、2个比它大的数,然后分类讨论一下即可。

找到的过程中把数sort以后,从大到小把它们的位置插入set,稍微维护一下即可。

#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
#define N 50001
#define MAXBIT 30
set<int>T;
typedef set<int>::iterator ER;
int root[N],ch[N*(MAXBIT+1)][2],sz[N*(MAXBIT+1)],tot;
int query(int L,int R,int W)//询问a[L...R]中W与其的最大异或值
{
    int ans=0;
    L=root[L-1];R=root[R];
    for(int i=MAXBIT-1;i>=0;--i)
      {
        int Bit=(W>>i&1^1);
        if(sz[ch[R][Bit]]-sz[ch[L][Bit]]==0)
          Bit^=1;
        else
          ans+=1<<i;
        R=ch[R][Bit];
        L=ch[L][Bit];
      }
    return ans;
}
void add(int now,int W)//先add(0,0),再add(1...n,a[1...n])
{
    int old=root[now-1];
    root[now]=++tot;
    now=root[now];
    for(int i=MAXBIT-1;i>=0;--i)
      {
        int Bit=(W>>i&1);
        sz[now]=sz[old]+1;
        ch[now][Bit^1]=ch[old][Bit^1];
        ch[now][Bit]=++tot;
        now=ch[now][Bit];
        old=ch[old][Bit];
      }
    sz[now]=sz[old]+1;
}
int n,ans,b[N],Ls[N],LLs[N],Rs[N],RRs[N];
struct Point{int x,y;};
bool operator < (const Point &a,const Point &b){return a.x<b.x;}
Point a[N];
int main()
{
	scanf("%d",&n);
	add(0,0);
	for(int i=1;i<=n;++i)
	  {
	  	scanf("%d",&a[i].x);
	  	add(i,a[i].x);
	  	a[i].y=i; b[i]=a[i].x;
	  }
	sort(a+1,a+n+1);
	for(int i=n;i>=1;--i)
	  {
	  	T.insert(a[i].y);
	  	ER it=T.find(a[i].y);
	  	if(it!=T.begin())
	  	  {
			--it;
			Ls[a[i].y]=*it;
			if(it!=T.begin())
			  {
			  	--it;
			  	LLs[a[i].y]=*it;
			  	++it;
			  }
			++it;
		  }
	  	if((++it)!=T.end())
	  	  {
			Rs[a[i].y]=*it;
			if((++it)!=T.end())
			  RRs[a[i].y]=*it;
			else
			  RRs[a[i].y]=n+1;
		  }
		else
		  Rs[a[i].y]=RRs[a[i].y]=n+1;
	  }
	for(int i=1;i<=n;++i)
	  {
	  	if(Ls[i])
	  	  ans=max(ans,query(LLs[i]+1,Rs[i]-1,b[i]));
	  	else if(RRs[i]!=n+1)
	  	  ans=max(ans,query(1,RRs[i]-1,b[i]));
	  	if(Rs[i]!=n+1)
	  	  ans=max(ans,query(Ls[i]+1,RRs[i]-1,b[i]));
	  	else if(LLs[i])
	  	  ans=max(ans,query(LLs[i]+1,n,b[i]));
	  }
	printf("%d\n",ans);
	return 0;
}
时间: 2024-10-01 00:22:11

【可持久化Trie】【set】bzoj3166 [Heoi2013]Alo的相关文章

BZOJ3166: [Heoi2013]Alo

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3166 按权值从大到小排序然后倒序插入set,set维护每个点的位置,然后区间就是前驱的前驱+1到后继的后继-1 . 然后维护一个可持久化trie就可以了. #include<cstring> #include<iostream> #include<cstdio> #include<algorithm> #include<set> #defin

bzoj3166: [Heoi2013]Alo 可持久化字典树

左右两边的比i大的最近的两个值.然后可持久化字典树即可. #include<bits/stdc++.h> using namespace std; int maxn=0,n,root[1600000],a[50010],cnt=0,l[1600000],r[1600000],p1[50010][25],p2[50010][25],sum[1600000],ans=0,pans=0,l1[50010],r1[50010],l2[50010],r2[50010]; void add(int &am

[您有新的未分配科技点]可,可,可持久化!?------0-1Trie和可持久化Trie普及版讲解

这一次,我们来了解普通Trie树的变种:0-1Trie以及在其基础上产生的可持久化Trie(其实,普通的Trie也可以可持久化,只是不太常见) 先简单介绍一下0-1Trie:一个0-1Trie节点只有两个子节点,分别代表0和1:从根节点开始,第一层代表限制的最高位,依次往下直到最底层,代表二进制第0位. 0-1Trie上的一条链所表示的数字,就是Trie树中的一个数字.0-1Trie除了节点和插入方式与普通的Trie树略有不同之外,其他操作都是和Trie树完全一样的.在维护这个节点插入过的siz

【bzoj3166】[Heoi2013]Alo 可持久化Trie树+STL-set

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

【BZOJ3166】Alo 可持久化trie树

首先我们枚举次大值,然后确定以这个数为次大值的最大区间. 这个区间就是左边第二个比它大的数的下标+1,右边第二个比它大的数的下标-1. 难就难在找到这个区间. 我们考虑将数排序,然后从大到小将数原来的下标插入set,此时set里的值都大于等于当前插入的数. 所以利用set找到前驱的前驱,后继的后继,就是我们需要的区间. 找到区间后,剩下的就是对于一个给定的数,在一段区间里找到一个数使其异或值最大,直接用可持久化trie就可以了. 1 #include <iostream> 2 #include

BZOJ 3166 HEOI2013 ALO 可持久化trie+st表

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3166(洛谷上也有) 题意概述: 给出一个序列,对于一个区间,其权值为区间中的次大值亦或区间中任意一个数的结果的最大值.求区间权值的最大值. 分析: 考虑每个点作为区间次大的状态,发现对于每个点至多有两个最长区间其为次大值(为了让异或结果最大当然是区间越长越好,选择最多),用二分+静态RMQ算出这两个区间再在可持久化trie上面贪心即可. 论如何现场yy可持久化数据结构23333(基于可

[BZOJ3261&amp;BZOJ3166]可持久化trie树及其应用

可持久化trie树 可持久化trie树现在想来是比较好理解的了,但却看了一个下午... 相当于对于每个状态建立一条链(或者说一棵trie),求解的时候只要让两个点按照相同的步子走然后看sum的大小关系即可. tr[y].son[p xor 1]:=tr[x].son[p xor 1]; tr[y].sum:=tr[x].sum+1; 这两句要好好体会,对之后理解query过程中的语句很有帮助. if (tr[tr[x].son[p xor 1]].sum=tr[tr[x].son[p xor 1

BZOJ 3166: [Heoi2013]Alo

3166: [Heoi2013]Alo Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 923  Solved: 437[Submit][Status][Discuss] Description Welcome to ALO ( Arithmetic and Logistic Online).这是一个VR MMORPG ,如名字所见,到处充满了数学的谜题.现在你拥有n颗宝石,每颗宝石有一个能量密度,记为ai,这些宝石的能量密度两两不同.现在你可以选

可持久化 trie 的简单入门

可持久化 $trie$  ....又是一个表里不一的东西..... 可持久化 $trie$  的介绍: 和主席树类似的,其实可持久化就是体现在前缀信息的维护上(搞不懂这怎么就叫做可持久化了...) $trie$ (字典树)大家应该都知道,就是一棵用来做字符串匹配的树, 但是!在这里,可持久化 $trie$ 就是完全不一样的东西了... 基本上(我做过的题),可持久化都是用来维护  $XOR$   信息的... 比如说求某个范围内的最大区间异或和之类的,至于到了树上嘛,你懂的. 可持久化 $tri