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