BZOJ #3166. [Heoi2013]Alo(可持久化trie树+set)

#3166. [Heoi2013]Alo

  • description
  • solution
  • code

BZOJ3166

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

solution

首先肯定是枚举每一个宝石的aia_iai作为次大值

区间[l,r][l,r][l,r]内与xxx异或的最大值,就是可持久化trie树

对于iii版本的trie树记录的是[1,i][1,i][1,i]的所有宝石信息

但是本题的难点是在于求出每个宝石做次大值时,有效的区间范围

定义前驱的含义:宝石密度大于aia_iai的在iii前面的距iii最近的宝石

定义后继的含义:宝石密度大于aia_iai的在iii后面的距iii最近的宝石

对于每个iii,询问的合法区间其实是前驱的前驱位置l加一,后继的后继位置r减一

  • 这里就有问题了,看似好像包含了两个比aia_iai大的宝石,iii宝石不再是次大值宝石

    • 其实并不是,要求包含前驱后继并不是意味着在(l,r)(l,r)(l,r)这个区间进行询问

      这个区间当然iii宝石是次次大值

    • 这是意味着两个独立区间的问题(l,i];[i,r)(l,i];[i,r)(l,i];[i,r)

      这么说的原因是,假设ai⨁aj(l<j<i<r)a_i\bigoplus a_j(l<j<i<r)aiaj(l<j<i<r)是最大值,那么相当于选择的区间是(l,i](l,i](l,i]

      同理假设ai⨁aj(l<i<j<r)a_i\bigoplus a_j(l<i<j<r)aiaj(l<i<j<r)是最大值,那么相当于选择的区间是[i,r)[i,r)[i,r)

      这样aia_iai在两个区间就扮演着次大值的角色了

    • 如果只是对于一个iii考虑前驱的位置加一到后继的后继位置减一,其实只是考虑了最大值在次大值aia_iai后面的区间,忽略了最大值在aia_iai前面的区间

    • 如果只是对于一个iii考虑前驱的前驱位置加一到后继的位置减一,其实只是考虑了最大值在次大值aia_iai前面的区间,忽略了最大值在aia_iai后面的区间

知道了选取区间端点的条件,代码怎么找呢?

  • set

具体而言:将宝石按照密度排序,按密度从大到小地加入宝石,set里面放的是宝石的下标iii,那么此时set里面的所有宝石都大于等于现在这个刚加进去的宝石密度

为了能阐释得更清楚,我们直接解读代码

首先是寻找后继的后继的位置,减一会在主函数的查询调用时减掉,这里暂时不考虑

  • 这里两个if语句的先后顺序是先让迭代器it自加后,再判断是否指向了setend()位置

  • 众所周知set是左闭右开的,end()位置是最后一个值的位置的下一个空位置

  • 先自加一,指向后继;再自加一,指向后继的后继

  • int find_r( int x ) {auto it = s.find( x );if( ++ it == s.end() ) return n + 1;if( ++ it == s.end() ) return n + 1;return *it;
    }
    

然后看寻找前驱的前驱代码,同样的加一操作在主函数的询问完成,这里不进行加一

  • 这里两个if语句的先后顺序是,先判断是否指向了begin()位置,再自减一

  • 第一个if如果成立,意味着当前加入的宝石下标最小,前驱都没有

  • 否则,迭代器就指向了前驱

  • 再到第二个if语句,如果成立,意味着前驱就是下标最小的宝石了,前驱的前驱没有

  • 否则迭代器就指向了前驱的前驱,达到目的

int find_l( int x ) {auto it = s.find( x );if( it -- == s.begin() ) return 0;if( it -- == s.begin() ) return 0;return *it;
}

最后还有一个代码细节

在插入操作和查询操作中,涉及到最后一层二进制位000的处理

void insert( int &now, int lst, int x, int d ) {if( d < 0 ) return;t[now = ++ cnt] = t[lst];t[now].sum ++;int k = x >> d & 1;insert( t[now].son[k], t[lst].son[k], x, d - 1 );
}int query( int l, int r, int x, int d ) {if( t[r].sum - t[l].sum == 0 ) return 0;if( d == 0 ) return 1;int k = x >> d & 1;if( t[t[r].son[k ^ 1]].sum - t[t[l].son[k ^ 1]].sum )return query( t[l].son[k ^ 1], t[r].son[k ^ 1], x, d - 1 ) + ( 1 << d );elsereturn query( t[l].son[k], t[r].son[k], x, d - 1 );
}

如果不在query操作设置if( d == 0 ) return 1的这个出口,在insert的时候就必须把二进制位−1-11建出来,即

void insert( int &now, int lst, int x, int d ) {t[now = ++ cnt] = t[lst];t[now].sum ++;if( d < 0 ) return;int k = x >> d & 1;insert( t[now].son[k], t[lst].son[k], x, d - 1 );
}int query( int l, int r, int x, int d ) {if( d < 0 ) return 0;if( t[r].sum - t[l].sum == 0 ) return 0;int k = x >> d & 1;if( t[t[r].son[k ^ 1]].sum - t[t[l].son[k ^ 1]].sum )return query( t[l].son[k ^ 1], t[r].son[k ^ 1], x, d - 1 ) + ( 1 << d );elsereturn query( t[l].son[k], t[r].son[k], x, d - 1 );
}

为什么呢?

  • 如果不在查询时设置最底层叶子的出口,那么就会进入对叶子左右儿子的if判断
  • 然而,插入操作又只在最底层叶子建点后就返回了
  • 所以叶子节点的儿子没有被分配过,贸然访问,完全不知道计算机会找到哪儿去
  • 我就是这个顺序细节问题,一直比答案少一

code

#include <set>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 50005
set < int > s;
pair < int, int > a[maxn];
int n, cnt;
int root[maxn];
struct { int son[2], sum; } t[maxn * 35];void insert( int &now, int lst, int x, int d ) {if( d < 0 ) return;t[now = ++ cnt] = t[lst];t[now].sum ++;int k = x >> d & 1;insert( t[now].son[k], t[lst].son[k], x, d - 1 );
}int query( int l, int r, int x, int d ) {if( t[r].sum - t[l].sum == 0 ) return 0;if( d == 0 ) return 1;int k = x >> d & 1;if( t[t[r].son[k ^ 1]].sum - t[t[l].son[k ^ 1]].sum )return query( t[l].son[k ^ 1], t[r].son[k ^ 1], x, d - 1 ) + ( 1 << d );elsereturn query( t[l].son[k], t[r].son[k], x, d - 1 );
}int find_l( int x ) {auto it = s.find( x );if( it -- == s.begin() ) return 0;if( it -- == s.begin() ) return 0;return *it;
}int find_r( int x ) {auto it = s.find( x );if( ++ it == s.end() ) return n + 1;if( ++ it == s.end() ) return n + 1;return *it;
}int main() {scanf( "%d", &n );for( int i = 1;i <= n;i ++ ) {scanf( "%d", &a[i].first );a[i].second = i;insert( root[i], root[i - 1], a[i].first, 30 );}sort( a + 1, a + n + 1 );int ans = 0;s.insert( a[n].second );for( int i = n - 1;i;i -- ) {s.insert( a[i].second );int l = find_l( a[i].second );int r = find_r( a[i].second );ans = max( ans, query( root[l], root[r - 1], a[i].first, 30 ) );}printf( "%d\n", ans );return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317056.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

洛谷P6054:开门大吉

Description\text{Description}Description P6054 开门大吉 nnn 位选手去参加节目“开门大吉”。共有 mmm 套题&#xff0c;每套题包含 ppp 个题目&#xff0c;第 iii 位选手答对第 jjj 套题中第 kkk 道的概率为 fi,j,kf_{i,j,k}fi,j,k​。 若一位选手答对第 iii 题&#xff0…

Docker最全教程之Ubuntu下安装Docker(十五)

前言Ubuntu是一个以桌面应用为主的开源GNU/Linux操作系统&#xff0c;应用很广。本篇主要讲述Ubuntu下使用SSH远程登录并安装Docker&#xff0c;并且提供了Docker安装的两种方式&#xff0c;希望对大家有所帮助。拥抱Linux&#xff0c;大家可以从Ubuntu开始&#xff01;Ubuntu下…

群论学习笔记

文章目录前言群基本定义&#xff1a;子群陪集拉格朗日定理正规子群交换群商群阶置换定义置换的乘法循环置换群群作用等价类不动点Burnside引理内容证明法1 轨道-稳定子定理法2Polya 定理所谓群论&#xff0c;就是对群体行为问题的讨论。 &#xff08;逃&#xff09; 前言 个人…

Super Jumping! Jumping! Jumping! HDU - 1087

Super Jumping! Jumping! Jumping! HDU - 1087 题意&#xff1a; 给定一条长度为n的序列&#xff0c;其中一定存在一条元素和最大的严格上升子序列&#xff0c;求这条序列的元素和。 题解&#xff1a; 最长上升序列模板题 代码&#xff1a; #include<bits/stdc.h> …

Codeforces Round #727 (Div. 2) 题解

文章目录A. Contest StartB. Love SongC. Stable GroupsD. PriceFixedE. Game with CardsF. Strange Array#727-Div.2A. Contest Start 数学题&#xff0c;分类讨论 一般的&#xff0c;一段区间[l,r][l,r][l,r]会对后面固定人数造成影响&#xff0c;假设是kkk最后kkk个人&…

潘淳(寒树Office):不务正业的公众号满月了,都写了些啥?

三喜临门一 喜今天真是个好日子&#xff0c;“流浪太阳”又回来了&#xff0c;阴雨绵绵长恨无期&#xff0c;今天苏州终于天晴&#xff0c;于是心情大好&#xff01;都说好心情会带来好运气&#xff0c;冥冥感觉要写点啥了&#xff0c;果不其然今天还有另外两喜。大早起来得…

G List it all

传送 题意&#xff1a; 题解&#xff1a; 我们来考虑以下样例&#xff1a;1&#xff0c;1&#xff0c;2 我们先考虑1的贡献&#xff1a;如图(图中只花了) 2&#xff01;表示还剩两个空位&#xff0c;还有两个数未填入&#xff0c;所以是2&#xff01;个 对于n个数重复&#x…

洛谷P4727:图的同构计数(Polya引理)(dfs)

解析 《关于我想了半天 dp 结果看题解 dfs 就行这回事》 我就说 gcd⁡\gcdgcd 这玩意 dp 个锤子啊… 拆分数的增长速度远没有想像中那么大&#xff0c;事实上&#xff0c;n60n60n60 也就 1e6 左右。 据题解说&#xff0c;这玩意的增长速度仅有 O(enn)O(\frac{e^{\sqrt n}}{n})…

ASP.NET Core 实战:基于 Dapper 扩展你的数据访问方法

一、前言在非静态页面的项目开发中&#xff0c;必定会涉及到对于数据库的访问&#xff0c;最开始呢&#xff0c;我们使用 Ado.Net&#xff0c;通过编写 SQL 帮助类帮我们实现对于数据库的快速访问&#xff0c;后来&#xff0c;ORM&#xff08;Object Relational Mapping&#x…

Codeforces Round #699 (Div. 2) 题解

文章目录A. Space NavigationB. New ColonyC. Fence PaintingD. AB GraphE. Sorting BooksF. AB Tree#699-Div.2A. Space Navigation 对于最终位置(x,y)&#xff0c;我们只关心那两个方向的字符是否足够即可 #include <cstdio> #include <cstring> #define maxn …

洛谷P4271:New Barns P(倍增)(LCT)(直径)

解析 倍增真香 关键性质&#xff1a;树上距离一个点最远的点必定是直径两端点其一。 本题限制好&#xff0c;要求少动态维护倍增数组暴力维护直径即可。 如果每次合并的是两棵树&#xff0c;而不是一棵树加一个点&#xff0c;可以先离线下来&#xff0c;照样能做。 如果每次强…

HDU 5510 Bazinga

HDU 5510 Bazinga 题意&#xff1a; 依次给你n个字符串&#xff0c;让你找到编号最大的字符串&#xff0c;存在一个比他编号小的字符串且不是其子串 题解&#xff1a; string中有find查找功能&#xff0c; 思路是用一个vector来存之前所有字符串&#xff0c;数组book用来表…

微软发布 Visual Studio 2019年第二季度路线图

微软近日发布了 Visual Studio 2019 年第二季度的路线图&#xff0c;路线图介绍了目前 VS 致力于在 VS 2019 发布的一些重要功能。官方表示&#xff0c;Visual Studio 2019 将继续按照 Visual Studio 发行周期流程提供更新&#xff0c;也就是约每 6 周推出一次次要更新&#xf…

Educational Codeforces Round 107 (Rated for Div. 2) 题解

文章目录A. Review SiteB. GCD LengthC. Yet Another Card DeckD. Min Cost StringE. Colorings and DominoesF. ChainwordG. Chips on a BoardEducational-Round-107A. Review Site 都给了两台机子&#xff0c;直接把所有只会投②的扔到一台&#xff0c;其余的全是另一台 就…

李争——一个骨子里是极客的程序员

我的业余作品《IT 英雄传》&#xff0c;聚焦身边的英雄&#xff0c;以文字采访的形式记录奇人趣事&#xff0c;笑看风云变幻。所写的人都是我见过面且比较熟悉的&#xff0c;绝大部分都是交往很久的&#xff0c;其中为了避嫌&#xff0c;我很少写微软同事&#xff0c;但今天这一…

Pagodas HDU - 5512

Pagodas HDU - 5512 题意&#xff1a; 一开始给你两个数a和b&#xff0c;你可以得到c通过&#xff0c;cab&#xff0c;或者ca-b&#xff0c;你所能得到的数的范围是1~n&#xff0c;两个人轮流操作&#xff0c;当有一方无法操作时&#xff0c;另一方获胜 题解&#xff1a; c…

期望学习笔记

前言 突然发现自己没有系统学过期望。 做一本通的时候是从二分图开始听的课&#xff0c;dp这一章只是四处搜题解而已。 做期望题基本都是靠玄学和《感性理解》 都是很简单的东西&#xff0c;但系统很重要&#xff0c;该补的还是要补的。 期望的基本性质 E(c)cE(c)cE(c)cE(cx)…

仅此一文让你明白事务隔离级别、脏读、不可重复读、幻读

网络上关于这方面的博文有些偏理论&#xff0c;有些通篇代码&#xff0c;都不能深入浅出。本文用图文并茂的方式&#xff0c;配上行云流水般的代码&#xff0c;非要摆清楚这个问题。相关代码已提交至码云&#xff08;点击这里下载&#xff09;。事务是现代关系型数据库的核心之…

[AtCoder Regular Contest 123] 题解

文章目录A - Arithmetic SequenceB - Increasing TriplesC - 1, 2, 3 - DecompositionD - Inc, Dec - DecompositionE - TrainingF - Insert AdditionARC123A - Arithmetic Sequence 大讨论 只能111&#xff0c;先固定中间的数&#xff0c;看两边加谁&#xff0c;如果都是加负…

2.5:模拟总结

文章目录前言考场题目解析T1T2T3总结代码T1T2T3前言 50pts 30020 rnk19 … 把1000ms看成10s我也真是个人才。 T3自然溢出50带模数T成20有点离谱。 但倒没有因为WA失分。 就是菜罢了 考场 这次时间管理还是比较合理的。 乍看三题觉得T1似乎是个伞兵题 这离线下来可持久化数组…