奶牛排队

一道好题,(可惜我直接看成最长上升子序列,居然还拿了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 }
原文地址:https://www.cnblogs.com/yufenglin/p/10765277.html