BZOJ3166: [Heoi2013]Alo

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3166

按权值从大到小排序然后倒序插入set,set维护每个点的位置,然后区间就是前驱的前驱+1到后继的后继-1 。

然后维护一个可持久化trie就可以了。

#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 50050
#define inf int(1e9)
#define ull unsigned long long
#define maxd 30
#define mm 1000000007
using namespace std;
set<int> q;
struct data{int x,id;
}a[maxn];
int s[maxn*40][2],sum[maxn*40],root[maxn],n,m,cnt,ans;
char ch[2];
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
void add(int d,int x,int &y,int val){
    y=++cnt; sum[y]=sum[x]+1;
    if (d<0) return;
    s[y][0]=s[x][0]; s[y][1]=s[x][1];
    int p=((val>>d)&1);
    add(d-1,s[x][p],s[y][p],val);
}
bool cmp(data a,data b){
    return a.x>b.x;
}
int ask(int d,int x,int y,int val){
    if (d<0) return 0;
    int p=((val>>d)&1);
    if (sum[s[y][p^1]]-sum[s[x][p^1]]>0) return (1<<d)+ask(d-1,s[x][p^1],s[y][p^1],val);
    else return ask(d-1,s[x][p],s[y][p],val);
}
int main(){
    n=read(); 
    rep(i,1,n) a[i].x=read(),a[i].id=i;
    rep(i,1,n) add(maxd,root[i-1],root[i],a[i].x);
    sort(a+1,a+1+n,cmp);
    q.insert(-1); q.insert(-2); q.insert(inf); q.insert(inf+1);
    q.insert(a[1].x);
    rep(i,2,n){
        int x=a[i].id,l,r;
        set<int>::iterator p,t;
        p=q.lower_bound(x);
        t=p; t++; r=*t-1;
        p--; p--; l=*p+1;
        l=max(l,1); r=min(r,n); 
        if (l!=r) ans=max(ans,ask(maxd,root[l-1],root[r],a[i].x));
        q.insert(x);
    }
    printf("%d\n",ans);
    return 0;
}

 

posted on 2015-12-22 19:16  ctlchild  阅读(146)  评论(0编辑  收藏  举报

导航