• [Heoi2013]Alo


    [Heoi2013]Alo

    每一个点作为贡献点的区间是包含一个比它大的值,所以我们对于每个点处理四个值

    \(L,R,L2,R2\)表示左边第一个比它大的,右边第一个,左边第二个,右边第二个~

    这些东西当然可以直接用set处理,但是可以前缀预处理+两边二分替换,甚至是第一遍二分也可以用单调栈代替,能跑得快一些

    那么这个点最大的可能贡献的区间就是\([L2+1,R-1]\)\([L+1,R2-1]\)

    接下来的问题就是对于一个值\(x\),求区间内的数与它的最大异或,这个我们用可持久化\(trie\)树等奇怪的数据结构实现

    #include<cstdio> 
    #include<cctype>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    using namespace std;
     
    #define reg register
    typedef long long ll;
    #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
     
    char IO;
    int rd(){
        int s=0,f=0;
        while(!isdigit(IO=getchar())) if(IO=='-') f=1;
        do s=(s<<1)+(s<<3)+(IO^'0');
        while(isdigit(IO=getchar()));
        return f?-s:s;
    }
     
    template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
    template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
     
     
    const int N=5e4+10;
     
    bool be;
     
    int n;
    int a[N];
    int rt[N],nxt[N*32][2];
    int m,s[N*32];
     
     
    void Pre_Make() {
        rep(i,1,n) {
            int p,pre=rt[i-1];
            p=rt[i]=++m;
            drep(j,29,0) {
                int x=((a[i]>>j)&1);
                nxt[p][x]=++m;
                nxt[p][!x]=nxt[pre][!x];
                p=nxt[p][x],pre=nxt[pre][x];
                s[p]=s[pre]+1;
            }
        }//预处理可持久化trie
    }
     
     
    int ans;
    void Que(int x,int l,int r) {
        l=rt[l-1],r=rt[r];
        int res=0;
        drep(i,29,0) {
            int t=(x&(1<<i))>0;
            if(s[nxt[r][!t]]-s[nxt[l][!t]]>0) res|=1<<i,l=nxt[l][!t],r=nxt[r][!t];
            else l=nxt[l][t],r=nxt[r][t];
        }
        ans=max(ans,res);//贪心查询
    }
     
    int stk[N],top;
    int L[N],R[N],LL[N],RR[N]; // LL=L2,RR=R2
     
    struct Node{
        int x,id,t;
        bool operator < (const Node __) const {
            return id<__.id;
        }
    }B[N];
    int cmp(const Node x,const Node y){
        return x.id>y.id;
    }
    int cnt;
     
    bool ed;
     
    int main(){
        n=rd();
        rep(i,1,n) a[i]=rd();
        Pre_Make();
        rep(i,1,n) {
            while(top && a[stk[top]]<a[i]) top--;
            L[i]=stk[top];
            if(L[i]>1) B[++cnt]=(Node){a[i],L[i]-1,i};
            stk[++top]=i;
        }
        top=0;
        sort(B+1,B+cnt+1);
        int p=1;//一遍单调栈+一遍二分预处理
        rep(i,1,n) {
            while(top && a[stk[top]]<a[i]) top--;
            stk[++top]=i;
            while(p<=cnt && B[p].id<=i) {
                int l=1,r=top,res=0;
                while(l<=r) {
                    int mid=(l+r)>>1;
                    if(a[stk[mid]]>B[p].x) l=mid+1,res=stk[mid];
                    else r=mid-1;
                    LL[B[p].t]=res;
                }
                p++;
            }
        }
        top=cnt=0;
        drep(i,n,1) {
            while(top && a[stk[top]]<a[i]) top--;
            R[i]=stk[top];
            if(R[i]<n && R[i]) B[++cnt]=(Node){a[i],R[i]+1,i};
            stk[++top]=i;
        }
        sort(B+1,B+cnt+1,cmp);
        p=1;
        top=0;
        drep(i,n,1) {
            while(top && a[stk[top]]<a[i]) top--;
            stk[++top]=i;
            while(p<=cnt && B[p].id>=i) {
                int l=1,r=top,res=0;
                while(l<=r) {
                    int mid=(l+r)>>1;
                    if(a[stk[mid]]>B[p].x) l=mid+1,res=stk[mid];
                    else r=mid-1;
                    RR[B[p].t]=res;
                }
                p++;
            }
        }
        rep(i,1,n) {
            if(!L[i] && !R[i]) continue;
            Que(a[i],LL[i]+1,RR[i]?RR[i]-1:n);
        }
        printf("%d\n",ans);
    }
     
     
    
  • 相关阅读:
    【iOS 实践笔记】UITableView顶部空白
    【iOS入门】dequeueReusableCellWithIdentifier:和dequeueReusableCellWithIdentifier:forIndexPath:的区别
    【iOS 入门】@class关键字
    【iOS 入门 动画学习】
    【android seekbar 增大拖动区域】
    【android 动画小技巧】一个控制顺序播放多个动画。
    【android 视频播放那些事之缓存】
    【java8 代码块新功能】
    Mac下使用gradlew命令
    Python格式符说明
  • 原文地址:https://www.cnblogs.com/chasedeath/p/11821070.html
Copyright © 2020-2023  润新知