码迷,mamicode.com
首页 > 其他好文 > 详细

Bzoj 3166 [Heoi2013] Alo 题解

时间:2017-10-25 23:54:15      阅读:237      评论:0      收藏:0      [点我收藏+]

标签:efi   最大   cst   out   script   lib   names   rip   mit   

3166: [Heoi2013]Alo

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 1118  Solved: 518
[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

5
9 2 1 4 7

Sample Output

14

HINT

【样例解释】 

选择区间[1,5],最大值为 7 xor 9。 
对于 100%的数据有 1 ≤ n ≤ 50000, 0 ≤ ai ≤ 10^9

Source

加强型数据By Hta

 

  又是一道大坑啊……

  习惯了求区间最大值,区间次大值怎么求呢?本题的n并不允许我们枚举区间,因此我们需要去求出每一个点的可选范围。既然该点是作为次大值出现在区间里,那么我们就要保证区间里有且只有一个比他大的。那么,他的取值范围就是他向左数第2个比他大的数+1~他向右数第2个比他大的数-1。当时看黄学长的时候黄学长说“前驱的前驱”脑子没反应过来,还以为是对他的前驱而言的前驱……

  区间知道了,那么怎么求最大值呢?如果说这道题我们不需要求这么多次区间异或最大值我们可以使用01trie树进行贪心。然而,由于这里我们要求好多次,普通的01trie并没有什么用,我们需要的是一个支持区间求异或最大值的数据结构——可持久化01trie.

  其实可持久化01trie打起来和不带修改的主席树没有太大的差别。毕竟都是二叉树。如果没有打过可以先去打一下主席树的模板题,求区间第K大。

  插入操作基本不变。在查询的时候我们利用前缀和,能让他异或后该位为1,且在这个区间里有满足要求的数,我们就选上并且沿着trie树向那个方向走,否则就向另一个方向走,可以把它理解为一个特殊的在trie树上的dfs。

技术分享
  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 #include <cmath>
  7 #include <queue>
  8 #include <set>
  9 #include <vector>
 10 #define N 50006
 11 #define lowbit(x) (x&(-x))
 12 using namespace std;
 13 int n,a[N],b[N];
 14 set<int> q;
 15 struct node{
 16     int size;
 17     node* ch[2];
 18     node() {
 19         size=0;
 20         ch[1]=ch[0]=0;
 21     }
 22 }*null=new node(),*root[N];
 23 node* newnode()
 24 {
 25     node* x=new node();
 26     x->ch[0]=x->ch[1]=null;
 27     return x;
 28 }
 29 void insert(node* la,node* now,int js,int x)
 30 {
 31     now->size=la->size+1;
 32     if(!js)return;
 33     if(x&(1ll<<(js-1)))
 34     {
 35         now->ch[0]=la->ch[0];
 36         now->ch[1]=newnode();
 37         insert(la->ch[1],now->ch[1],js-1,x);
 38     }
 39     else
 40     {
 41         now->ch[1]=la->ch[1];
 42         now->ch[0]=newnode();
 43         insert(la->ch[0],now->ch[0],js-1,x);  
 44     }
 45 }
 46 long long que(node* l,node* r,int x)
 47 {
 48     long long ans=0;
 49     for(int i=32;i>=1;i--)
 50     {
 51         if(x&(1ll<<(i-1)))
 52         {
 53             if(r->ch[0]->size-l->ch[0]->size)
 54             {
 55                 ans|=(1ll<<(i-1));
 56                 l=l->ch[0];
 57                 r=r->ch[0];
 58             }
 59             else
 60             {
 61                 r=r->ch[1];
 62                 l=l->ch[1];
 63             }
 64         }
 65         else
 66         {
 67             if(r->ch[1]->size-l->ch[1]->size) 
 68             {
 69                 ans|=(1ll<<(i-1));
 70                 l=l->ch[1];
 71                 r=r->ch[1];
 72             }
 73             else
 74             {
 75                 r=r->ch[0];
 76                 l=l->ch[0];
 77             }
 78         }
 79     }
 80     return ans;
 81 }
 82 bool px(int x,int y)
 83 {
 84     return a[x]>a[y];
 85 }
 86 int main()
 87 {
 88     null->ch[0]=null->ch[1]=null;
 89     root[0]=newnode();
 90     scanf("%d",&n);
 91     for(int i=1;i<=n;i++)
 92     {
 93         root[i]=newnode();
 94         scanf("%d",&a[i]);
 95         insert(root[i-1],root[i],32,a[i]);
 96         b[i]=i;
 97     }
 98     sort(b+1,b+n+1,px);
 99     long long ans=0;
100     q.insert(-2);q.insert(-1);
101     q.insert(1000000002);q.insert(1000000003);
102     q.insert(b[1]);
103     for(int i=2;i<=n;i++)
104     {
105         set<int>::iterator it,p;
106         p=it=q.lower_bound(b[i]);
107         int r,l;
108         it++;r=*it-1;
109         p--;p--; l=*p+1;
110         l=max(l,1);r=min(r,n);
111         if(l!=r)ans=max(ans,que(root[l-1],root[r],a[b[i]]));
112         q.insert(b[i]); 
113     }
114     printf("%lld\n",ans);
115     return 0;
116 }
View Code

 

Bzoj 3166 [Heoi2013] Alo 题解

标签:efi   最大   cst   out   script   lib   names   rip   mit   

原文地址:http://www.cnblogs.com/liutianrui/p/7726918.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!