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;
    }
    
    
  • 相关阅读:
    my first android test
    VVVVVVVVVV
    my first android test
    my first android test
    my first android test
    ini文件
    ZZZZ
    Standard Exception Classes in Python 1.5
    Python Module of the Week Python Module of the Week
    my first android test
  • 原文地址:https://www.cnblogs.com/Mychael/p/8946423.html
Copyright © 2011-2022 走看看