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>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 50050
#define inf int(1e9)
#define ull unsigned long long
#define maxd 30
#define mm 1000000007
using namespace std;
set<int> q;
struct data{int x,id;
}a[maxn];
int s[maxn*40][2],sum[maxn*40],root[maxn],n,m,cnt,ans;
char ch[2];
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch==‘-‘) f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-‘0‘; ch=getchar();}
    return x*f;
}
void add(int d,int x,int &y,int val){
    y=++cnt; sum[y]=sum[x]+1;
    if (d<0) return;
    s[y][0]=s[x][0]; s[y][1]=s[x][1];
    int p=((val>>d)&1);
    add(d-1,s[x][p],s[y][p],val);
}
bool cmp(data a,data b){
    return a.x>b.x;
}
int ask(int d,int x,int y,int val){
    if (d<0) return 0;
    int p=((val>>d)&1);
    if (sum[s[y][p^1]]-sum[s[x][p^1]]>0) return (1<<d)+ask(d-1,s[x][p^1],s[y][p^1],val);
    else return ask(d-1,s[x][p],s[y][p],val);
}
int main(){
    n=read();
    rep(i,1,n) a[i].x=read(),a[i].id=i;
    rep(i,1,n) add(maxd,root[i-1],root[i],a[i].x);
    sort(a+1,a+1+n,cmp);
    q.insert(-1); q.insert(-2); q.insert(inf); q.insert(inf+1);
    q.insert(a[1].x);
    rep(i,2,n){
        int x=a[i].id,l,r;
        set<int>::iterator p,t;
        p=q.lower_bound(x);
        t=p; t++; r=*t-1;
        p--; p--; l=*p+1;
        l=max(l,1); r=min(r,n);
        if (l!=r) ans=max(ans,ask(maxd,root[l-1],root[r],a[i].x));
        q.insert(x);
    }
    printf("%d\n",ans);
    return 0;
}
时间: 2024-10-28 11:31:42

BZOJ3166: [Heoi2013]Alo的相关文章

【可持久化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

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

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,这些宝石的能量密度两两不同.现在你可以选

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

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

P4098 [HEOI2013]ALO 可持久化01Trie

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

【BZOJ3166】Alo 可持久化trie树

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

BZOJ 3166 HEOI2013 Alo 可持久化Trie树

题目大意:给定一个不重复的序列a,在a中任选一个区间,求区间内的次大值与区间内的任意一个其它数的最大的异或值 首先我们枚举次大值 对于一个次大值 它可能选择的另一个数的取值范围为(l,r) 其中l为这个数左侧第二个比它大的数 r为这个数右侧第二个比它大的数 在这个区间内的Trie树中贪心寻找最大值即可 这个区间怎么求呢?我们维护一棵平衡树 将数从大到小将下标加进平衡树 每加进一个下标 比它大的数的下标都在平衡树中 求两次后继就是r 求两次前驱就是l 我偷懒写了set-- #include<set

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

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

[HEOI2013]ALO

https://zybuluo.com/ysner/note/1238170 题面 现在你拥有\(n\)颗宝石,每颗宝石有一个能量密度,记为\(a_i\).现在你可以选取连续的一些宝石(必须多于一个)进行融合,则融合而成的宝石的能量密度为这些宝石中能量密度的次大值与其他任意一颗宝石的能量密度按位异或的值. 现在你需要知道你怎么选取需要融合的宝石,才能使生成的宝石能量密度最大. \(n\leq5*10^4\) 题面 显然要可持久化\(Trie\)树. 唯一有点费脑子的地方是次大值. 在一个区间找次