题目

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}。
现在你需要知道你怎么选取需要融合的宝石,才能使生成的宝石能量密度最大。

输入格式

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

输出格式

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

输入样例

5

9 2 1 4 7

输出样例

14

提示

【样例解释】

选择区间[1,5],最大值为 7 xor 9。

对于 100%的数据有 1 ≤ n ≤ 50000, 0 ≤ ai ≤ 10^9

题解

我们枚举那个次大值的位置,然后我们找的可操作区间肯定是越大越好
然后用二分 + ST表找出最大的区间使得它为这个区间的最大值
要成为次大值,就跨过其中一个区间端点即可

然后就可以在可持久化trie树上询问答案了

注意区间边界的处理细节

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 50005,B = 30,maxm = 100005,INF = 1000000000;
inline int read(){int out = 0,flag = 1; char c = getchar();while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}return out * flag;
}
int n,Log[maxn],bin[40],A[maxn],mx[maxn][17];
struct trie{int ch[maxn * 35][2],sum[maxn * 35],rt[maxn],cnt;int ins(int r,int x){int tmp,u;tmp = u = ++cnt;for (int i = B; i >= 0; i--){ch[u][0] = ch[r][0];ch[u][1] = ch[r][1];sum[u] = sum[r] + 1;int t = x & bin[i]; t >>= i;r = ch[r][t];u = ch[u][t] = ++cnt;}sum[u] = sum[r] + 1;return tmp;}int query(int u,int v,int x,int dep){if (dep < 0) return 0;LL t = x & bin[dep]; t >>= dep;if (sum[ch[u][t ^ 1]] - sum[ch[v][t ^ 1]])return bin[dep] + query(ch[u][t ^ 1],ch[v][t ^ 1],x,dep - 1);return query(ch[u][t],ch[v][t],x,dep - 1);}
}T;
int getmx(int l,int r){int t = Log[r - l + 1];return max(mx[l][t],mx[r - bin[t] + 1][t]);
}
void init(){bin[0] = 1; REP(i,35) bin[i] = bin[i - 1] << 1;Log[0] = -1; for (int i = 1; i < maxn; i++) Log[i] = Log[i >> 1] + 1;n = read();REP(i,n){mx[i][0] = A[i] = read();T.rt[i] = T.ins(T.rt[i - 1],A[i]);}REP(j,16) REP(i,n){if (i + bin[j] - 1 > n) break;mx[i][j] = max(mx[i][j - 1],mx[i + bin[j - 1]][j - 1]);}
}
void solve(){int l,r,mid,L,R,ans = 0;for (int i = 1; i <= n; i++){if (i == 1 || A[i - 1] >= A[i]) L = i;else {l = 0; r = i - 1;while (l < r){mid = l + r + 1 >> 1;if (getmx(i - mid,i - 1) < A[i]) l = mid;else r = mid - 1;}L = i - l;}if (i == n || A[i + 1] >= A[i]) R = i;else {l = 0; r = n - i;while (l < r){mid = l + r + 1 >> 1;if (getmx(i + 1,i + mid) < A[i]) l = mid;else r = mid - 1;}R = i + l;}if (L == 1 && R == n) continue;if (R < n){int tmp = R;R++;if (R == n || A[R + 1] >= A[i]) l = 0;else {l = 0; r = n - R;while (l < r){mid = l + r + 1 >> 1;if (getmx(R + 1,R + mid) < A[i]) l = mid;else r = mid - 1;}R += l;}if (L < R) ans = max(ans,T.query(T.rt[R],T.rt[L - 1],A[i],B));R = tmp;}if (L > 1){L--;if (L == 1 || A[L - 1] >= A[i]) l = 0;else {l = 0; r = L - 1;while (l < r){mid = l + r + 1 >> 1;if (getmx(L - mid,L - 1) < A[i]) l = mid;else r = mid - 1;}L -= l;}if (L < R) ans = max(ans,T.query(T.rt[R],T.rt[L - 1],A[i],B));}}printf("%d\n",ans);
}
int main(){init();solve();return 0;
}

转载于:https://www.cnblogs.com/Mychael/p/8946423.html

BZOJ3166 [Heoi2013]Alo 【可持久化trie树 + 二分 + ST表】相关推荐

  1. BZOJ3473:字符串(后缀数组,主席树,二分,ST表)

    Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 一 ...

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

    #3166. [Heoi2013]Alo description solution code BZOJ3166 description Welcome to ALO ( Arithmetic and ...

  3. 【bzoj3261】最大异或和 可持久化Trie树

    题目描述 给定一个非负整数序列 {a},初始长度为 N.        有M个操作,有以下两种操作类型: 1.A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1. 2.Q l r x: ...

  4. P4735 最大异或和(可持久化trie树、求最大区间异或和)

    P4735 最大异或和 我们维护一个前缀异或和:s[i]=a[1]xora[2]xor-a[i−1]xora[i]s[i] = a[1] \ xor\ a[2]\ xor\ - a[i-1] \ xo ...

  5. BZOJ 3261 最大异或和 可持久化Trie树

    题目大意:给定一个序列,提供下列操作: 1.在数组结尾插入一个数 2.给定l,r,x,求一个l<=p<=r,使x^a[p]^a[p+1]^...^a[n]最大 首先我们能够维护前缀和 然后 ...

  6. BZOJ3261 最大异或和 解题报告(可持久化Trie树)

    本题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3261 题目描述 给定一个非负整数序列{a},初始长度为N. 有M个操作,有以下两种操作类 ...

  7. HDU - 4757 Tree(LCA+可持久化trie树)

    题目链接:点击查看 题目大意:给出一棵有有n个节点的树,每个点都有一个权值,现在给出m个查询,每次查询的形式为:x,y,z,求出从点x到点y的路径上任选一点,使其与z的异或值最大,输出异或值 题目分析 ...

  8. BZOJ3261: 最大异或和(可持久化trie树)

    题意 题目链接 Sol 设\(sum[i]\)表示\(1 - i\)的异或和 首先把每个询问的\(x \oplus sum[n]\)就变成了询问前缀最大值 可持久化Trie树维护前缀xor,建树的时候 ...

  9. B. Integers Have Friends(cf)二分 + st表

    原题链接:Problem - 1548B - Codeforces 解决RMQ(区间最值)问题的算法. 总结的来说求rmq问题有多种方法:线段树,ST表等 线段树预处理O(nlogn),查询O(log ...

最新文章

  1. Pandownload 下线了,我花了 30 分钟自己搭建了一个网盘
  2. 怎么修改nginx的access.log的时间格式
  3. Java中JDBC进阶教程之数据库的隔离级别!
  4. 6-1 数组元素的区间删除
  5. raise errorclass(errno, errval) sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1366, u
  6. 【使用注意】特殊中括号[]的特殊json数组
  7. 游戏建模之3Dmax的重要性
  8. 安川e7变频器接线_台达变频器C2000系列在铝箔纸压花机上的应用
  9. oracle 下和 db2的syscat 对应的,oracle db2命令对比(整理中)
  10. 链家程序员怒删 9TB 数据,被判 7 年!
  11. Mysql 查询某个字段最长的记录
  12. Unity 贴图自动匹配材质工具 贴图自动添加到材质球工具 材质球匹配贴图工具 Substance Painter制作的贴图自动匹配材质球工具
  13. 电子政务工程建设项目可行性研究报告编制要求
  14. 疫情在家办公,向日葵突然卡死,无法远程电脑的解决办法(局域网远程强制重启windows)
  15. 一周电子取证行业热点简讯
  16. 2021年中国保险行业现状:全年新增保单件数489亿件,保险金额为12146万亿元[图]
  17. 2022-2027年中国建筑施工机械租赁市场规模预测及投资战略咨询报告
  18. Win11蓝屏代码0x0000001A的解决方法
  19. ITEXT 把表格定位在固定位置
  20. qt获取文件 图片大小

热门文章

  1. Go 学习笔记(77)— Go 第三方库之 cronexpr(解析 crontab 表达式,定时任务)
  2. 【Design pattern】设计模式思路总结(三)
  3. 对装饰器@wraps的解释(一看就懂)-- 并对装饰器详解
  4. NCHW与NHWC格式
  5. 多机多卡训练基本原理
  6. Python:urllib2模块的URLError与HTTPError
  7. [JAVA EE] Filter过滤器
  8. HarmonyOS UI 开发 vp ,fp , px 以及写具体数字的 理解
  9. Python bytes 的使用
  10. 数据库MySQL/mariadb知识点——索引