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;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注