3166: [Heoi2013]Alo
这题大意是给你一个序列,求一个最优区间[l,r],使其中的次大值xor上区间中任意另一个数,使xor和最大(对不起,我又语死了)
这题其实暴力能a= =
但是写暴力太没节操了(- -b)
网上似乎没有除暴力以外的题解= =我来写一篇吧= =
我的大致想法就是用线段树维护i前面第二个比他大的值f[i](这里可以用权值线段树),然后用函数式trie找(f[i]+1,i)上与a[i]的最大xor。。
貌似很基础的样子= =也很暴力= =
有更优解请告诉我= =
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=3000010; struct re{ int l,r,lc,rc,ms,mf; } t[N]; int root[N],col[N],a[N],b[N],c[N],d[N]; int tr[N][2]; int n,sum=0,num=0,tot=0,ans=0; inline void inse(int pp,int i,int x){ root[i]=++sum; int pos=root[i]; col[pos]=i; for (int j=30;j>=0;j--){ int y=(x>>j)&1; tr[pos][y^1]=tr[pp][y^1]; tr[pos][y]=++sum; col[sum]=i; pos=tr[pos][y]; pp=tr[pp][y]; } } inline int ques(int l,int r,int x){ int pos=root[r]; int ans=0; for (int j=30;j>=0;j--){ int z=(x>>j)&1; if (col[tr[pos][z^1]]>=l){ ans+=1<<j; pos=tr[pos][z^1]; }else pos=tr[pos][z]; } return ans; } inline int buildtree(int l,int r){ int x=++num; t[x].l=l; t[x].r=r; t[x].mf=t[x].ms=0; if (l==r){ t[x].lc=t[x].rc=0; return x; } int mm=(l+r)/2; t[x].lc=buildtree(l,mm); t[x].rc=buildtree(mm+1,r); return x; } inline void renew(int c,int x){ if (t[x].mf<c){ t[x].ms=t[x].mf; t[x].mf=c; return; } if (t[x].mf==c) return; if (t[x].ms<c) t[x].ms=c; } inline void down(int x){ int l=t[x].lc,r=t[x].rc; renew(t[x].ms,l); renew(t[x].mf,l); renew(t[x].ms,r); renew(t[x].mf,r); } inline int query(int x,int pos){ if (t[x].l==t[x].r) return t[x].ms; down(x); int mm=(t[x].l+t[x].r)/2; if (pos<=mm) return query(t[x].lc,pos); return query(t[x].rc,pos); } inline void add(int x,int l,int r,int c){ if (t[x].l==0) return; if (l<=t[x].l&&t[x].r<=r){ t[x].ms=t[x].mf; t[x].mf=c; return; } down(x); int mm=(t[x].l+t[x].r)/2; if (l<=mm) add(t[x].lc,l,r,c); if (mm<r) add(t[x].rc,l,r,c); } inline void calc(){ memset(col,0,sizeof(col)); memset(tr,0,sizeof(tr)); sum=0; tot=0; inse(0,0,0); for (int i=1;i<=n;i++){ b[++tot]=a[i]; inse(root[i-1],i,a[i]); } std::sort(b+1,b+n+1); for (int i=1;i<=n;i++){ c[i]=lower_bound(b+1,b+n+1,a[i])-b; } num=0; int ro=buildtree(1,n); for (int i=1;i<=n;i++){ int x; x=query(ro,c[i]); x++; ans=max(ans,ques(x,i,a[i])); if (c[i]>1) add(ro,1,c[i]-1,i); } } inline void read(int &T){ int ch=getchar(); while (ch<'0'||ch>'9'){ ch=getchar(); } T=0; while (ch>='0'&&ch<='9'){ T=T*10+ch-'0'; ch=getchar(); } } int main(){ scanf("%d",&n); num=0; for (int i=1;i<=n;i++){ scanf("%d",&d[i]); a[i]=d[i]; } calc(); for (int i=1;i<=n;i++) a[i]=d[n-i+1]; calc(); printf("%d\n",ans); }