BZOJ 3166: [Heoi2013]Alo
3166: [Heoi2013]Alo
Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 923 Solved: 437
[Submit][Status][Discuss]
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
9 2 1 4 7
Sample Output
HINT
【样例解释】
选择区间[1,5],最大值为 7 xor 9。
对于 100%的数据有 1 ≤ n ≤ 50000, 0 ≤ ai ≤ 10^9
Source
首先,应该枚举选择哪个数字作为次大值,然后需要知道其对应的可以选取哪个范围内的数字作为题目中的$ap$。
范围可以通过预处理得到,方法是先用二分得到每个数左侧第一个大于这个数的地方,然后再二分出第二个大于这个数的地方。每个数到两侧第二个大于这个数的范围就是$ap$的可选范围,不含第二个大于这个数的数字。
然后,问题转化为求一个数字在一个区间内的最大异或数字,这个问题是经典的Trie树问题,尽量“反着跑”即可。但是有区间限制,并且是n组询问,所以可以用大佬的可持久化Trie或我这种蒟蒻的莫队+Trie解决。
#include <bits/stdc++.h> const int siz = ; int n, num[siz]; int st_maxi[siz][]; inline void preworkST(void)
{
for (int i = ; i <= n; ++i)
st_maxi[i][] = num[i]; for (int i = ; i < ; ++i)
for (int j = ; j <= n; ++j)
if (j + ( << i) - <= n)
st_maxi[j][i] = std::max(
st_maxi[j][i - ],
st_maxi[j + ( << (i - ))][i - ]);
} inline int stMax(int l, int r)
{
if (l > r)return -; int len = r - l + , log = ; while (len >= ( << (log + )))++log; return std::max(
st_maxi[l][log],
st_maxi[r - ( << log) + ][log]);
} int nt_pre[siz];
int nt_nxt[siz]; inline void preworkNT(void)
{
for (int i = ; i <= n; ++i)
{
int val = num[i], lt = , rt = i, mid, pos = , ans = ; while (lt <= rt)
{
mid = (lt + rt) >> ; if (stMax(mid, i) > val)
lt = mid + , pos = mid;
else
rt = mid - ;
} lt = , rt = pos - ; while (lt <= rt)
{
mid = (lt + rt) >> ; if (stMax(mid, pos - ) > val)
lt = mid + , ans = mid;
else
rt = mid - ;
} nt_pre[i] = ans;
} for (int i = ; i <= n; ++i)
{
int val = num[i], lt = i, rt = n, mid, pos = n, ans = n; while (lt <= rt)
{
mid = (lt + rt) >> ; if (stMax(i, mid) > val)
rt = mid - , pos = mid;
else
lt = mid + ;
} lt = pos + , rt = n; while (lt <= rt)
{
mid = (lt + rt) >> ; if (stMax(pos + , mid) > val)
rt = mid - , ans = mid;
else
lt = mid + ;
} nt_nxt[i] = ans;
}
} struct query {
int l, r, t, ans;
}q[siz]; int s; inline bool cmp(const query &a, const query &b)
{
if (a.l / s != b.l / s)
return a.l < b.l;
else
return a.r < b.r;
} const int tri = ; int next[tri][], sum[tri], tot = ; inline void insert(int t)
{
int p = ; for (int i = ; i >= ; --i)
{
int c = (t >> i) & ; if (!next[p][c])
next[p][c] = ++tot; p = next[p][c]; ++sum[p];
}
} inline void remove(int t)
{
int p = ; for (int i = ; i >= ; --i)
{
int c = (t >> i) & ; if (!next[p][c])
next[p][c] = ++tot; p = next[p][c]; --sum[p];
}
} inline int query(int t)
{
int ret = , p = ; for (int i = ; i >= ; --i)
{
int c = (t >> i) & ; if (sum[next[p][c^]])
p = next[p][c^], ret |= ( << i);
else if (sum[next[p][c]])
p = next[p][c];
else
return ;
} return ret;
} signed main(void)
{
scanf("%d", &n); for (int i = ; i <= n; ++i)
scanf("%d", num + i); preworkST(); preworkNT(); for (int i = ; i <= n; ++i)
{
q[i].l = nt_pre[i];
q[i].r = nt_nxt[i];
q[i].t = num[i];
q[i].ans = ;
} s = sqrt(n); std::sort(q + , q + + n, cmp); int lt = , rt = , maxi = stMax(, n); for (int i = ; i <= n; ++i)
{
while (lt < q[i].l)remove(num[lt++]);
while (lt > q[i].l)insert(num[--lt]);
while (rt > q[i].r)remove(num[rt--]);
while (rt < q[i].r)insert(num[++rt]);
if (q[i].t != maxi)q[i].ans = query(q[i].t);
} int answer = ; for (int i = ; i <= n; ++i)
answer = std::max(answer, q[i].ans); printf("%d\n", answer);
}
@Author: YouSiki
BZOJ 3166: [Heoi2013]Alo的更多相关文章
- bzoj 3166 [Heoi2013]Alo 可持久化Trie
3166: [Heoi2013]Alo Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1227 Solved: 569[Submit][Status ...
- Bzoj 3166 [Heoi2013] Alo 题解
3166: [Heoi2013]Alo Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1118 Solved: 518[Submit][Status ...
- BZOJ 3166 HEOI2013 ALO 可持久化trie+st表
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3166(洛谷上也有) 题意概述: 给出一个序列,对于一个区间,其权值为区间中的次大值亦或区 ...
- BZOJ 3166 [HEOI2013]Alo (可持久化01Trie+链表)
题目大意:给你一个长度为$n$的序列,让你找出一段子序列,求其中的 次大值 异或 序列里一个数 能得到的最大值 先对序列建出可持久化$Trie$ 按元素的值从小到大遍历,设当前元素的位置是i,找出它左 ...
- BZOJ 3166: [Heoi2013]Alo 链表+可持久化trie
链表这个东西非常好用啊 ~ code: #include <bits/stdc++.h> #define N 50010 #define inf 2000400000 #define se ...
- BZOJ3166: [Heoi2013]Alo
3166: [Heoi2013]Alo Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 394 Solved: 204[Submit][Status] ...
- [BZOJ3166][Heoi2013]Alo 可持久化Trie树
3166: [Heoi2013]Alo Time Limit: 20 Sec Memory Limit: 256 MB DescriptionWelcome to ALO ( Arithmetic a ...
- P4098 [HEOI2013]ALO
最近这个家伙去哪了,为啥一直不更博客了呢?原来他被老师逼迫去补了一周的文化课,以至于不会把班里的平均分拉掉太多.好了,我们来看下面这道题目: P4098 [HEOI2013]ALO 题目描述 Welc ...
- 【BZOJ3166】[Heoi2013]Alo 可持久化Trie树+set
[BZOJ3166][Heoi2013]Alo Description Welcome to ALO ( Arithmetic and Logistic Online).这是一个VR MMORPG , ...
随机推荐
- Revit开发小技巧——撤销操作
最近开发Revit命令需要限制某些操作,思路是监控用户操作,如果达到限制条件,将操作回退.思路有两种: 1.调用WindowsAPI,发送快捷命令Ctrl+Z. 2.通过Revit底层提供DLL找到回 ...
- java并发之线程池的使用
背景 当系统并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要消耗大量的系统资源. 所以需要一个办法使得线程可以 ...
- vue处理循环列表动态数据问题
调用方法:Vue.set( target, key, value ) target:要更改的数据源(可以是对象或者数组) key:要更改的具体数据 value :重新赋的值 <!DOCTYPE ...
- JavaScript学习笔记(六)—— 异步编码
第七章 异步编码 1 事件处理程序 处理程序:即网页加载完毕后将执行的代码,称回调函数或监听器: 包含:处理函数+window.onload=函数名; <script language=&qu ...
- jsp内置对象 转发与重定向的区别
jsp 内置对象 转发与重定向的比较 重定向和转发有一个重要的不同:当使用转发时,JSP容器将使用一个内部的方法来调用目标页面,新的页面继续处理同一个请求,而浏览器将不会知道这个过程. 与之相反,重 ...
- day13 内置函数
参考资料: https://www.processon.com/view/link/5b4ee15be4b0edb750de96ac 内置函数: 作⽤域相关: locals() 返回当前作用域 ...
- Python-opencv摄像头图像捕获
实例一 (灰色调度) #!/usr/bin/env python # _*_ coding:utf-8 _*_ import cv2 as cv import numpy as np capture ...
- 【贪心算法】POJ-1328 区间问题
一.题目 Description Assume the coasting is an infinite straight line. Land is in one side of coasting, ...
- week4c:个人博客作业
6.具体程序: #include<stdio.h>#include<stdlib.h>#include<math.h>void Udecide_n();int De ...
- C1WPF制作OLAP Cube浏览工具
经过前期一段时间对WPF的学习了解,相信大家对WPF有了一定的了解.今天我们一起来了解使用Component One(简称C1)的WPF控件制作CUBE浏览工具.其实这个OLAP控件官方已经有了很详细 ...