P4098 [HEOI2013]ALO

题目

P4098 [HEOI2013]ALO

为了个水题,调了快两个小时\(emmm\)

做法

暴力当然也能过,好像还不太好卡,数两两不同,所以两两限制通过特判的时间复杂度应该也是很优秀的,可惜\(juruo\)不会算,希望有\(dalao\)能求出大概的复杂度

操作的区间为[左边第二大+1,右边第二大-1]

本来想单调栈处理[左边第一大+1,右边第二大-1],但这样[左边第二大+1,左边第一大]这样的区间就没算

然后又想\(nL[i]=L[L[i]]+1,nR[i]=R[R[i]]-1\),又错了,这样\(\{4,5,7,1\}\)其中\(1\)的左区间会到达第一个数

正解:\(a\)从小到达排,每次把最小的数的位置在双向链表删掉,然后向左右边找当然,你也可以去肛主席树或平衡树

My complete code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
#include<stack>
using namespace std;
typedef long long LL;
const LL maxn=3000000;
inline LL Read(){
	LL x(0),f(1);char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
	return x*f;
}
stack<LL>sta;
LL n,ans,M;
LL a[maxn],L[maxn],R[maxn],pre[maxn],nxt[maxn];
struct Trie{
	LL nod;
	LL len,val[maxn],son[maxn][2],d[40],root[maxn];
	inline void Build(LL &now,LL pre){
        val[now=++nod]=val[pre]+1;
        LL tmp(now);
        for(LL i=32;i>=1;--i){
            son[tmp][d[i]^1]=son[pre][d[i]^1];
            son[tmp][d[i]]=++nod;
            tmp=son[tmp][d[i]],pre=son[pre][d[i]];
            val[tmp]=val[pre]+1;
        }
    }
    inline void First(LL val){
        LL len(0);
        while(val){
            d[++len]=val&1;
            val>>=1;
        }
        for(LL i=len+1;i<=32;++i) d[i]=0;
    }
    inline void Insert(LL now,LL pre,LL val){
        First(val);
        Build(root[now],root[pre]);
    }
    inline LL Query(LL pre,LL now){
        LL ans(0);
        for(LL i=32;i>=1;--i){
            if(val[son[now][d[i]^1]]-val[son[pre][d[i]^1]]>0){
                ans|=(1<<(i-1));
                now=son[now][d[i]^1],pre=son[pre][d[i]^1];
            }else{
                now=son[now][d[i]],pre=son[pre][d[i]];
            }
        }return ans;
    }
    inline LL Solve(LL pre,LL now,LL val){
        First(val);
        return Query(root[pre-1],root[now]);
    }
}T;
struct node{
	LL val,id;
	bool operator <(const node &x)const{
		return val<x.val;
	}
}p[maxn];
int main(){
	n=Read();
	for(LL i=1;i<=n;++i){
	    a[i]=Read();
	    T.Insert(i,i-1,a[i]);
	    p[i]=(node){a[i],i};
		pre[i]=i-1;nxt[i]=i+1;
	}
	pre[0]=1; nxt[n]=n;
	sort(p+1,p+1+n);
	for(LL i=1;i<=n;++i){
		LL now(p[i].id);
		nxt[pre[now]]=nxt[now],pre[nxt[now]]=pre[now];
		L[now]=pre[pre[now]],R[now]=nxt[nxt[now]];
	}
	for(LL i=1;i<=n;++i)
			ans=max(ans,T.Solve(L[i]+1,R[i]-1,a[i]));
	printf("%lld",ans);
	return 0;
}/*
*/
posted @ 2019-01-25 21:31  y2823774827y  阅读(280)  评论(1编辑  收藏  举报