题意:
给出n个数,定义num为任意区间的最大值和次大值得异或,求num的最大值
思路:枚举每一个数作为次大值,那么最大值可以用线段树找次大数右边或左边的第一个比他大的数,这样就找到最大值了
样例:
5
5 2 1 4 3
答案为:7
代码:
#include <cstdio> #include <iostream> using namespace std; #define N 100001 int a[N]; struct st { int x,y,m; }p[N * 4]; void build(int r,int x,int y) { p[r].x = x;p[r].y = y; if(x == y) { p[r].m = a[x]; return ; } int mid = (p[r].x + p[r].y) >> 1,tem = r << 1; build(tem,x,mid); build(tem | 1,mid + 1,y); p[r].m = max(p[tem].m,p[tem | 1].m); } int R_query(int r,int x,int y,int v) { if(p[r].m < v) return -1; if(p[r].x == x && p[r].y == y && x == y && p[r].m > v) { return p[r].m; } int mid = (p[r].x + p[r].y) >> 1,tem = r << 1; if(x > mid) return R_query(tem | 1,x,y,v); else if(y <= mid) return R_query(tem,x,y,v); else { int u1,u2; u1 = R_query(tem | 1,mid + 1,y,v); if(u1 > v) return u1; u2 = R_query(tem,x,mid,v); if(u2 > v) return u2; return -1; } } int L_query(int r,int x,int y,int v) { if(p[r].m < v) return -1; if(p[r].x == x && p[r].y == y && x == y && p[r].m > v) { return p[r].m; } int mid = (p[r].x + p[r].y) >> 1,tem = r << 1; if(y <= mid) return L_query(tem,x,y,v); else if(x > mid) return L_query(tem | 1,x,y,v); else { int u1,u2; u2 = L_query(tem,x,mid,v); if(u2 > v) return u2; u1 = L_query(tem | 1,mid + 1,y,v); if(u1 > v) return u1; return -1; } } int main() { int n,s = 0,k; scanf("%d",&n); for(int i = 1;i <= n;i ++) scanf("%d",&a[i]); build(1,1,n); for(int i = 2;i <= n;i ++) { k = R_query(1,1,i - 1,a[i]); k = k ^ a[i]; if(k > s) s = k; } for(int i = 1;i < n;i ++) { k = L_query(1,i + 1,n,a[i]); k = k ^ a[i]; if(k > s) s = k; } printf("%d\n",s); return 0; }