BZOJ3166 [Heoi2013]Alo [Persistent trie tree + binary + ST table]

topic

Welcome to ALO ​​(Arithmetic and Logistic Online). It's a VR MMORPG that,
as the name suggests, is full of math puzzles.
Now you have n gems, each gem has an energy density, denoted ai, and the energy
density of these gems is different in pairs. Now you can select some consecutive gems (must be more than one) for fusion, set them as ai, ai+1, …, aj, then the energy density of the fused gems will be the second largest value of the energy density in these gems
and the other The energy density of any gemstone is the value of bitwise exclusive OR, that is, if the second largest
value of the energy density of the gemstone is k, the energy density of the generated gemstone is max{k xor ap | ap ≠ k , i ≤ p ≤ j}.
Now you need to know how you choose the gems you need to fuse to maximize the energy density of the resulting gems.

input format

The first line, an integer n, represents the number of gems.
In the second line, n integers, representing a1 to an respectively, represent the energy density of each gemstone, ensuring that ai ≠ aj for i ≠ j.

output format

Output a line with an integer representing the maximum gem energy density that can be generated.

input sample

5

9 2 1 4 7

Sample output

14

hint

【Example explanation】

Choose the interval [1,5] with a maximum value of 7 xor 9.

For 100% of the data there are 1 ≤ n ≤ 50000, 0 ≤ ai ≤ 10^9

answer

We enumerate the position of the second largest value, and then the operable interval we find must be as large as possible,
and then use the dichotomy + ST table to find the largest interval so that it is the largest value of this interval.
To become the second largest value, just cross the One of the endpoints of the interval can be

Then you can ask the answer on the persistent trie

Pay attention to the details of the processing of interval boundaries

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 50005,B = 30,maxm = 100005,INF = 1000000000;
inline int read(){
    int out = 0,flag = 1; char c = getchar();
    while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    return out * flag;
}
int n,Log[maxn],bin[40],A[maxn],mx[maxn][17];
struct trie{
    int ch[maxn * 35][2],sum[maxn * 35],rt[maxn],cnt;
    int ins(int r,int x){
        int tmp,u;
        tmp = u = ++cnt;
        for (int i = B; i >= 0; i--){
            ch[u][0] = ch[r][0];
            ch[u][1] = ch[r][1];
            sum[u] = sum[r] + 1;
            int t = x & bin[i]; t >>= i;
            r = ch[r][t];
            u = ch[u][t] = ++cnt;
        }
        sum[u] = sum[r] + 1;
        return tmp;
    }
    int query(int u,int v,int x,int dep){
        if (dep < 0) return 0;
        LL t = x & bin[dep]; t >>= dep;
        if (sum[ch[u][t ^ 1]] - sum[ch[v][t ^ 1]])
            return bin[dep] + query(ch[u][t ^ 1],ch[v][t ^ 1],x,dep - 1);
        return query(ch[u][t],ch[v][t],x,dep - 1);
    }
}T;
int getmx(int l,int r){
    int t = Log[r - l + 1];
    return max(mx[l][t],mx[r - bin[t] + 1][t]);
}
void init(){
    bin[0] = 1; REP(i,35) bin[i] = bin[i - 1] << 1;
    Log[0] = -1; for (int i = 1; i < maxn; i++) Log[i] = Log[i >> 1] + 1;
    n = read();
    REP(i,n){
        mx[i][0] = A[i] = read();
        T.rt[i] = T.ins(T.rt[i - 1],A[i]);
    }
    REP(j,16) REP(i,n){
        if (i + bin[j] - 1 > n) break;
        mx[i][j] = max(mx[i][j - 1],mx[i + bin[j - 1]][j - 1]);
    }
}
void solve(){
    int l,r,mid,L,R,ans = 0;
    for (int i = 1; i <= n; i++){
        if (i == 1 || A[i - 1] >= A[i]) L = i;
        else {
            l = 0; r = i - 1;
            while (l < r){
                mid = l + r + 1 >> 1;
                if (getmx(i - mid,i - 1) < A[i]) l = mid;
                else r = mid - 1;
            }
            L = i - l;
        }
        if (i == n || A[i + 1] >= A[i]) R = i;
        else {
            l = 0; r = n - i;
            while (l < r){
                mid = l + r + 1 >> 1;
                if (getmx(i + 1,i + mid) < A[i]) l = mid;
                else r = mid - 1;
            }
            R = i + l;
        }
        if (L == 1 && R == n) continue;
        if (R < n){
            int tmp = R;
            R++;
            if (R == n || A[R + 1] >= A[i]) l = 0;
            else {
                l = 0; r = n - R;
                while (l < r){
                    mid = l + r + 1 >> 1;
                    if (getmx(R + 1,R + mid) < A[i]) l = mid;
                    else r = mid - 1;
                }
                R += l;
            }
            if (L < R) ans = max(ans,T.query(T.rt[R],T.rt[L - 1],A[i],B));
            R = tmp;
        }
        if (L > 1){
            L--;
            if (L == 1 || A[L - 1] >= A[i]) l = 0;
            else {
                l = 0; r = L - 1;
                while (l < r){
                    mid = l + r + 1 >> 1;
                    if (getmx(L - mid,L - 1) < A[i]) l = mid;
                    else r = mid - 1;
                }
                L -= l;
            }
            if (L < R) ans = max(ans,T.query(T.rt[R],T.rt[L - 1],A[i],B));
        }
    }
    printf("%d\n",ans);
}
int main(){
    init();
    solve();
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324843222&siteId=291194637