【BZOJ3166】Alo 可持久化trie树

首先我们枚举次大值,然后确定以这个数为次大值的最大区间。

这个区间就是左边第二个比它大的数的下标+1,右边第二个比它大的数的下标-1。

难就难在找到这个区间。

我们考虑将数排序,然后从大到小将数原来的下标插入set,此时set里的值都大于等于当前插入的数。

所以利用set找到前驱的前驱,后继的后继,就是我们需要的区间。

找到区间后,剩下的就是对于一个给定的数,在一段区间里找到一个数使其异或值最大,直接用可持久化trie就可以了。

 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <set>
 7 
 8 using namespace std;
 9 
10 const int N = 100000 + 5;
11 const int len = 30;
12 
13 namespace Trie{
14     int tot, root[N];
15     int son[N*50][2], cnt[N*50];
16     void insert( int y, int &x, int num, int d ){
17         cnt[x = ++tot] = cnt[y]+1;
18         if ( d < 0 ) return;
19         int p = (num>>d)&1;
20         son[x][p^1] = son[y][p^1];
21         insert(son[y][p],son[x][p],num,d-1);
22     }
23     int query( int x, int y, int num, int d ){
24         if ( d < 0 ) return 0;
25         int p = (num>>d)&1;
26         int k = cnt[son[y][p^1]]-cnt[son[x][p^1]];
27         if ( k ) return query(son[x][p^1],son[y][p^1],num,d-1)+(1<<d);
28         else return query(son[x][p],son[y][p],num,d-1);
29     }
30 }
31 
32 using namespace Trie;
33 
34 int n, ans, w[N], k[N];
35 
36 set <int> s;
37 set <int> ::iterator it;
38 
39 bool cmp( const int &A, const int &B ){
40     return w[A] > w[B];
41 }
42 
43 int Getl( int x ){
44     it = s.find(x);
45     if ( it-- == s.begin() ) return 0;
46     if ( it-- == s.begin() ) return 0;
47     return *it;
48 }
49 int Getr( int x ){
50     it = s.find(x);
51     if ( ++it == s.end() ) return n+1;
52     if ( ++it == s.end() ) return n+1;
53     return *it;
54 }
55 
56 int main(){
57     scanf( "%d", &n );
58     for ( int i = 1; i <= n; i ++ )    scanf( "%d", &w[i] );
59     for ( int i = 1; i <= n; i ++ )    k[i] = i;
60     sort( k + 1 , k + 1 + n , cmp );
61     for ( int i = 1; i <= n; i ++ )
62         insert(root[i-1],root[i],w[i],len);    
63     s.insert(k[1]);
64     for ( int i = 2; i <= n; i ++ ){
65         s.insert(k[i]);
66         int l = Getl(k[i]);
67         int r = Getr(k[i]);
68         int x = w[k[i]];
69         int temp = query(root[l],root[r-1],x,len);
70         ans = max( ans,temp );
71     }
72     printf( "%d\n", ans );    
73 
74     return 0;
75 }
View Code

 

posted @ 2016-02-28 11:29  羁旅  阅读(158)  评论(0编辑  收藏  举报