题意:
找到一个区间,设 k k k位区间次大值,求 m a x ( k ⊕ a [ i ] ∣ l ≤ i ≤ r ) max(k \oplus a[i]|l\le i \le r) max(k⊕a[i]∣l≤i≤r)
题解:
首先考虑某个值为次大值的区间,有且仅有一个值比他大,这个可以排序+set求出。
然后求区间与一个值的异或最大值就是可持久化trie经典题了。
code:
#include<set>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
struct node{int a,num;}a[50010];
bool cmp(node a,node b) {return a.a>b.a;}
struct trnode{int lc,rc,c;}tr[3000010];int tot=0,root[50010];
void change(int &x,int k,int d)
{
tr[++tot]=tr[x];x=tot;
if(k==-1) {tr[x].c++;return;}
int c=(d&(1<<k))?1:0;
if(!c) change(tr[x].lc,k-1,d);
else change(tr[x].rc,k-1,d);
tr[x].c=tr[tr[x].lc].c+tr[tr[x].rc].c;
}
set<int> s;
int ans=0;
void solve(int d,int l,int r)
{
//printf("%d %d %d\n",d,l,r);
int s=0;
int x1=root[l-1],x2=root[r];
for(int i=30;i>=0;i--)
{
s<<=1;
int c=((1<<i)&d)?1:0;
int lcc=tr[tr[x2].lc].c-tr[tr[x1].lc].c;
int rcc=tr[tr[x2].rc].c-tr[tr[x1].rc].c;
//printf("c:%d %d\n",c,rcc);
//if(s) printf("put:%d %d %d\n",i,lcc,rcc);
if(c)
{
if(lcc) x1=tr[x1].lc,x2=tr[x2].lc;
else x1=tr[x1].rc,x2=tr[x2].rc,s++;
}
else
{
if(rcc) x1=tr[x1].rc,x2=tr[x2].rc,s++;
else x1=tr[x1].lc,x2=tr[x2].lc;
}
}
//printf("s:%d\n",s);
ans=max(ans,s^d);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].a);a[i].num=i;
root[i]=root[i-1];
change(root[i],30,a[i].a);
}
sort(a+1,a+n+1,cmp);
s.insert(0);s.insert(n+1);
s.insert(a[1].num);
for(int i=2;i<=n;i++)
{
//printf("a:%d %d\n",a[i].a,a[i].num);
int l=*(--s.lower_bound(a[i].num)),r=*s.lower_bound(a[i].num);
//printf("l r:%d %d\n",l,r);
if(l!=0) solve(a[i].a,*(--(--s.lower_bound(a[i].num)))+1,r-1);
if(r!=n+1) solve(a[i].a,l+1,(*(++s.upper_bound(a[i].num)))-1);
s.insert(a[i].num);
}
printf("%d",ans);
}