一道好题,(可惜我直接看成最长上升子序列,居然还拿了20分?
题目大意:给定一组数,求出一个最长的区间,满足区间最左端最小,最右端最大。(注意:内部不能有和两侧相等的数)
解法:分治+线段树
考虑一段连续的区间l到r,如果该区间内最小值的位置在最大值前,那么从最小值到最大值的这一段区间就是一组合法且对于该区间(指的是最小值到最大值的这一段区间)的最优解,那么我们递归剩余两部分就行
如果在后面,那么我们无法确定是否有一组最优解,但是我们可以分成三个区间(正确性很显然,如果有一个解涉及到两个区间,那么它一定在内部有一个极小值或极大值使得它不满足条件),依次递归下去就行
那么我们现在的问题就是怎么去求最小值和最大值的位置,这个可以用线段树进行维护,递归时间复杂度O(n),线段树查询logn,所以总复杂度nlogn
最后,附上本题代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<iostream> 5 //Debug Yufenglin 6 #define dej printf("Running "); 7 #define dep1(x) cout<<#x<<"="<<x<<endl; 8 #define dep2(x,y) cout<<#x<<"="<<x<<' '<<#y<<"="<<y<<endl; 9 #define dep3(x,y,z) cout<<#x<<"="<<x<<' '<<#y<<"="<<y<<' '<<#z<<"="<<z<<endl; 10 11 //Standfor Yufenglin 12 #define LL long long 13 #define LB long double 14 #define reg register 15 #define il inline 16 #define maxn 100000 17 #define inf 100000000 18 using namespace std; 19 20 LL n,maxans,minans,ans,mn,mx; 21 LL q[maxn+5]; 22 struct TREE 23 { 24 LL l,r,maxv,minv,maxid,minid; 25 }; 26 TREE tree[maxn*4+5]; 27 28 void build(LL ll,LL rr,LL k) 29 { 30 tree[k].l=ll,tree[k].r=rr; 31 if(tree[k].l==tree[k].r) 32 { 33 tree[k].maxv=tree[k].minv=q[ll]; 34 tree[k].maxid=tree[k].minid=ll; 35 return; 36 } 37 LL mid=(ll+rr)>>1; 38 build(ll,mid,(k<<1)); 39 build(mid+1,rr,(k<<1)+1); 40 if(tree[(k<<1)].maxv>tree[(k<<1)+1].maxv) tree[k].maxid=tree[(k<<1)].maxid; 41 else tree[k].maxid=tree[(k<<1)+1].maxid; 42 if(tree[(k<<1)].minv>tree[(k<<1)+1].minv) tree[k].minid=tree[(k<<1)+1].minid; 43 else tree[k].minid=tree[(k<<1)].minid; 44 tree[k].maxv=max(tree[(k<<1)].maxv,tree[(k<<1)+1].maxv); 45 tree[k].minv=min(tree[(k<<1)].minv,tree[(k<<1)+1].minv); 46 } 47 void query(LL x,LL y,LL k) 48 { 49 if(tree[k].l>=x&&tree[k].r<=y) 50 { 51 if(maxans<tree[k].maxv) mx=tree[k].maxid; 52 if(minans>tree[k].minv) mn=tree[k].minid; 53 maxans=max(maxans,tree[k].maxv); 54 minans=min(minans,tree[k].minv); 55 return; 56 } 57 int mid=(tree[k].l+tree[k].r)>>1; 58 if(x<=mid) query(x,y,(k<<1)); 59 if(y>mid) query(x,y,(k<<1)+1); 60 } 61 void dfs(LL lft,LL rit) 62 { 63 if(lft>=rit) return; 64 maxans=0,minans=100000000000000000; 65 query(lft,rit,1); 66 if(mn<mx) 67 { 68 ans=max(ans,mx-mn+1); 69 dfs(lft,mn-1); 70 dfs(mx+1,rit); 71 } 72 else 73 { 74 dfs(lft,mn-1); 75 dfs(mn,mx); 76 dfs(mx+1,rit); 77 } 78 } 79 int main() 80 { 81 scanf("%lld",&n); 82 for(int i=1; i<=n; i++) 83 { 84 scanf("%lld",&q[i]); 85 } 86 build(1,n,1); 87 dfs(1,n); 88 if(ans==1) ans=0; 89 printf("%lld ",ans); 90 return 0; 91 }