zoukankan      html  css  js  c++  java
  • Bzoj 3166 [Heoi2013] Alo 题解

    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
    ",ans);
    115     return 0;
    116 }
    View Code
  • 相关阅读:
    webstorm
    呐,这是某蒟蒻幼稚的博客 ~~Welcome
    CSP-S 2021 补题记录
    CSP-S 2021 游记
    Tarjan 算法小结
    FHQ Treap 浅析
    2048游戏 (C++ Windows)
    线段树 算法分析
    树状数组 算法分析
    数学期望(ξ) 浅析
  • 原文地址:https://www.cnblogs.com/liutianrui/p/7726918.html
Copyright © 2011-2022 走看看