BZOJ 3166 HEOI2013 ALO 可持久化trie+st表
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3166(洛谷上也有)
题意概述:
给出一个序列,对于一个区间,其权值为区间中的次大值亦或区间中任意一个数的结果的最大值。求区间权值的最大值。
分析:
考虑每个点作为区间次大的状态,发现对于每个点至多有两个最长区间其为次大值(为了让异或结果最大当然是区间越长越好,选择最多),用二分+静态RMQ算出这两个区间再在可持久化trie上面贪心即可。
论如何现场yy可持久化数据结构23333(基于可持久化线段树的yy算法)
注意一下算区间的边界问题。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<set> 9 #include<map> 10 #include<vector> 11 #include<cctype> 12 using namespace std; 13 const int MAXN=50005; 14 15 int N,a[MAXN]; 16 struct data{ int l,r,v; }q[MAXN<<1]; int cnt; 17 int mx[MAXN][18]; 18 struct Trie{ 19 static const int maxn=1600000; 20 static const int maxm=50005; 21 int np,root[maxm],to[maxn][2],sum[maxn]; 22 Trie(){ np=sum[0]=0; memset(to[0],0,sizeof(to[0])); } 23 int copynode(int p){ 24 memcpy(to[++np],to[p],sizeof(to[p])); 25 sum[np]=sum[p]; 26 return np; 27 } 28 void ins(int ver,int x){ 29 root[ver]=copynode(root[ver-1]); 30 int p=root[ver],d; 31 for(int i=30;i>=0;i--){ 32 sum[p]++,d=(x>>i)&1; 33 if(!to[p][d]){ 34 to[p][d]=++np,sum[np]=0; 35 memset(to[np],0,sizeof(to[np])); 36 p=to[p][d]; 37 } 38 else to[p][d]=copynode(to[p][d]),p=to[p][d]; 39 } 40 sum[p]++; 41 } 42 int query(int A,int B,int w){ 43 int p1=root[A],p2=root[B],d; 44 for(int i=30;i>=0;i--){ 45 d=((w>>i)&1)^1; 46 if(sum[to[p2][d]]-sum[to[p1][d]]) 47 p1=to[p1][d],p2=to[p2][d],w^=d<<i; 48 else p1=to[p1][d^1],p2=to[p2][d^1],w^=1-d<<i; 49 } 50 return w; 51 } 52 }trie; 53 54 void _scanf(int &x) 55 { 56 x=0; 57 char c=getchar(); 58 while(c<'0'||c>'9') c=getchar(); 59 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 60 } 61 void data_in() 62 { 63 _scanf(N); 64 for(int i=1;i<=N;i++) _scanf(a[i]); 65 } 66 void get_st() 67 { 68 for(int i=1;i<=N;i++) mx[i][0]=a[i]; 69 for(int i=N;i>=1;i--) 70 for(int j=1;(1<<j)<=N-i+1;j++) 71 mx[i][j]=max(mx[i][j-1],mx[i+(1<<j-1)][j-1]); 72 } 73 int query(int x,int y) 74 { 75 int k=0; 76 while((1<<k+1)<y-x+1) k++; 77 return max(mx[x][k],mx[y-(1<<k)+1][k]); 78 } 79 int getp1(int p,int v) 80 { 81 int re=p,mid,L=1,R=p; 82 while(L<R){ 83 mid=L+R>>1; 84 if(query(mid,p-1)>v) L=mid+1; 85 else R=mid,re=mid; 86 } 87 return re; 88 } 89 int getp2(int p,int v) 90 { 91 int re=p,mid,L=p+1,R=N+1; 92 while(L<R){ 93 mid=L+R>>1; 94 if(query(p+1,mid)>v) R=mid; 95 else L=mid+1,re=mid; 96 } 97 return re; 98 } 99 void work() 100 { 101 get_st(); 102 for(int i=1;i<=N;i++){ 103 int p1=getp1(i,a[i]),p2=getp2(i,a[i]); 104 if(p1>1) q[++cnt]=(data){getp1(p1-1,a[i]),p2,a[i]}; 105 if(p2<N) q[++cnt]=(data){p1,getp2(p2+1,a[i]),a[i]}; 106 } 107 for(int i=1;i<=N;i++) trie.ins(i,a[i]); 108 int ans=0; 109 for(int i=1;i<=cnt;i++) 110 ans=max(ans,trie.query(q[i].l-1,q[i].r,q[i].v)); 111 printf("%d\n",ans); 112 } 113 int main() 114 { 115 data_in(); 116 work(); 117 return 0; 118 }