BZOJ - 3166 可持久化Trie 维护次大区间

题意:给出\(a[1...n]\),找出一个连续区间\(a[l...r],r>l\),令该区间的次大值为\(a_k\),使得\(a_k⊕a_i,l≤i≤r\)最大,输出全局最优解

(这题意有点别扭)

异或这种套路,一般都是上trie,区间异或就加个可持久化

但问题是怎么找区间

不妨令每一个\(a_i\)为当前区间的次大值,那我们的目标就是尽可能找出该次大值的最远左右边界

\(a_i\)从大到小插入,使用平衡树动态维护位置,那么\(pos_i\)的前驱和后继都是比\(a_i\)大的值的下标

假设第一个比\(a_i\)大的左边界下标是\(L1\),第二个比它大的是\(L2\),既\(L2<L1\)

同理设\(R2>R1\)

那么符合条件的极大区间就是\([L1+1,R2-1]\)\([L2+1,R1-1]\)

对于字典树上求异或最大值并不需要严格区分两个极大区间,那么我们直接求出\([L2+1,R2-1]\)的异或最大值即可

PS.这回代码写着有点飘

#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define iter(i,j) for(int i=0;i<(j).size();i++)
#define print(a) printf("%lld",(ll)a)
#define println(a) printf("%lld\n",(ll)a)
#define printbk(a) printf("%lld ",(ll)a)
#define IOS ios::sync_with_stdio(0)
using namespace std;
const int MAXN = 5e4+11;
const int oo = 0x3f3f3f3f;
typedef long long ll;
ll read(){
    ll x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int T[MAXN],a[MAXN],b[MAXN];
struct TRIE{
    int tot;
    int son[MAXN*35][2],size[MAXN*35];
    void init(){
        tot=0;
        son[0][0]=son[0][1]=size[0]=0;
        memset(T,0,sizeof T);
    }
    int insert(int old,int val){
        int rt,o;rt=o=++tot;
        rrep(i,30,0){
            son[o][0]=son[old][0],
            son[o][1]=son[old][1];
            size[o]=size[old]+1;
            int wh=val>>i&1;
            son[o][wh]=++tot;
            old=son[old][wh];
            o=son[o][wh];
        }
        size[o]=size[old]+1;
        return rt;
    }
    int query(int l,int r,int val){
        int ans=0;
        rrep(i,30,0){
            int wh=val>>i&1;
            if(size[son[r][wh^1]]-size[son[l][wh^1]]){
                ans|=(1<<i),r=son[r][wh^1],l=son[l][wh^1];
            }else{
                r=son[r][wh],
                l=son[l][wh];
            }
        }
        return ans;
    }
}trie;
struct QAQ{
    int pos;ll val;
    bool operator<(const QAQ &ORZ)const{
        return val>ORZ.val;
    }
}c[MAXN];
int main(){
    int n,m;
    while(cin>>n){
        trie.init();
        rep(i,1,n) c[i]=(QAQ){i,read()};
        rep(i,1,n) T[i]=trie.insert(T[i-1],c[i].val);
        set<int> s;
        int orz[]={-1,-2,-3,oo,oo+1,oo+2};
        rep(i,0,5) s.insert(orz[i]);
        sort(c+1,c+1+n);
        int ans=0;
        rep(i,1,n){
            int l,r,now;;
            s.insert(l=r=now=c[i].pos);
            if(i==1) continue;
            set<int>::iterator it,old;
            it=old=s.find(now);
            it--;it--; l=(*it)+1;
            it=old;
            it++;it++; r=(*it)-1;
            l=max(1,l);r=min(r,n);
            ans=max(ans,trie.query(T[l-1],T[r],c[i].val));
        }
        println(ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/caturra/p/9465709.html