zoukankan      html  css  js  c++  java
  • BZOJ3166 [Heoi2013]Alo 【可持久化trie树 + 二分 + ST表】

    题目

    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}。
    现在你需要知道你怎么选取需要融合的宝石,才能使生成的宝石能量密度最大。

    输入格式

    第一行,一个整数 n,表示宝石个数。
    第二行, n个整数,分别表示a1至an,表示每颗宝石的能量密度,保证对于i ≠ j有 ai ≠ aj。

    输出格式

    输出一行一个整数,表示最大能生成的宝石能量密度。

    输入样例

    5

    9 2 1 4 7

    输出样例

    14

    提示

    【样例解释】

    选择区间[1,5],最大值为 7 xor 9。

    对于 100%的数据有 1 ≤ n ≤ 50000, 0 ≤ ai ≤ 10^9

    题解

    我们枚举那个次大值的位置,然后我们找的可操作区间肯定是越大越好
    然后用二分 + ST表找出最大的区间使得它为这个区间的最大值
    要成为次大值,就跨过其中一个区间端点即可

    然后就可以在可持久化trie树上询问答案了

    注意区间边界的处理细节

    #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
    ",ans);
    }
    int main(){
    	init();
    	solve();
    	return 0;
    }
    
    
  • 相关阅读:
    定位公众号页面,跳转之后 vuejs 失效问题
    Java发展前景与职业方向解析
    Java中BIO,NIO,AIO的理解
    Java中最常见的十道面试题
    java策略模式
    细思极恐-你真的会写java吗?
    Java中最常见的十道面试题
    细思极恐-你真的会写java吗?
    如何突破 Java 程序员的分水岭
    35 个 Java 代码性能优化总结
  • 原文地址:https://www.cnblogs.com/Mychael/p/8946423.html
Copyright © 2011-2022 走看看