【单调栈】Vijos P1926 紫色的手链
题目链接:
题目大意:
给n个数(n<=100 000),求任意区间的最大值异或次大值的最大值。
题目思路:
【模拟】【单调栈】
我们维护一个严格单调递减队列,存放当前的数字,初始为前两个数字。
每当加入新的元素时,依次与栈头的元素比较,每次比较更新ans(当作该元素与栈头元素构成的区间解,因为是严格单调递减序列,所以这两个元素是最大和次大的,否则栈头已经被弹出),如果新的元素比栈头元素大,就将栈头元素弹出,重复以上的比较,更新解,弹出栈头操作,直到结束。因为每个数字只会进栈出栈一次,所以时间复杂度是O(n)。
(说得有点拙计,如果没看懂可以自己稍微画画样例什么的,或者留言~)
1 // 2 //by coolxxx 3 // 4 #include<iostream> 5 #include<algorithm> 6 #include<string> 7 #include<iomanip> 8 #include<memory.h> 9 #include<time.h> 10 #include<stdio.h> 11 #include<stdlib.h> 12 #include<string.h> 13 #include<stdbool.h> 14 #include<math.h> 15 #define min(a,b) ((a)<(b)?(a):(b)) 16 #define max(a,b) ((a)>(b)?(a):(b)) 17 #define abs(a) ((a)>0?(a):(-(a))) 18 #define lowbit(a) (a&(-a)) 19 #define sqr(a) (a)*(a) 20 #define swap(a,b) (a)^=(b),(b)^=(a),(a)^=(b) 21 #define eps 1e-8 22 #define MAX 0x7f7f7f7f 23 #define INF 20000 24 #define PI 3.1415926535897 25 #define N 100004 26 using namespace std; 27 int n,m,lll,ans,cas; 28 int a[N]; 29 int main() 30 { 31 #ifndef ONLINE_JUDGE 32 // freopen("1.txt","r",stdin); 33 // freopen("2.txt","w",stdout); 34 #endif 35 int i,j,k; 36 while(~scanf("%d",&n) && n) 37 { 38 scanf("%d%d",&a[1],&a[2]); 39 lll=2;ans=a[1]^a[2]; 40 for(i=3;i<=n;i++) 41 { 42 scanf("%d",&k); 43 while(lll>0 && k>a[lll])j=a[lll--]^k,ans=max(ans,j); 44 if(lll>0)ans=max(ans,a[lll]^k); 45 a[++lll]=k; 46 } 47 printf("%d\n",ans); 48 } 49 return 0; 50 } 51 52 53 /* 54 // 55 56 // 57 */