• 奶牛排队


    一道好题,(可惜我直接看成最长上升子序列,居然还拿了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 }
  • 相关阅读:
    两个服务器上SQLServer实例之间配置Service Broker示例
    处理数据库镜像问题的一个案例
    oracel修改密码
    Oracle报错
    如何创建ORACLE大文件表空间
    创建、删除表空间
    oracle中新建用户和赋予权限
    非常全的VsCode快捷键
    VS Code常用快捷键
    启动Weblogic问题集锦
  • 原文地址:https://www.cnblogs.com/yufenglin/p/10765277.html
Copyright © 2020-2023  润新知