• uva1471 Defense Lines


    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=1<<29;
    
    int n,a[maxn];
    int f[maxn],g[maxn];
    struct Node
    {
        int x,y;
        friend bool operator<(Node A,Node B)
        {
            return A.x<B.x;
        }
    };Node q[maxn];int len;
    
    int main()
    {
        freopen("in.txt","r",stdin);
        int T;cin>>T;
        while(T--){
            scanf("%d",&n);
            REP(i,1,n) scanf("%d",&a[i]);
            if(n==0){
                cout<<0<<endl;
                continue;
            }
            g[1]=1;REP(i,2,n) g[i]=a[i]>a[i-1]?g[i-1]+1:1;
            f[n]=1;for(int i=n-1;i>=1;i--) f[i]=a[i]<a[i+1]?f[i+1]+1:1;
            //cout<<n<<endl;REP(i,1,n) cout<<a[i]<<" ";cout<<endl;
            //REP(i,1,n) cout<<f[i]<<" ";cout<<endl;
            //REP(i,1,n) cout<<g[i]<<" ";cout<<endl;
            int ans=1;
            q[len=1]={a[1],g[1]};
            REP(i,2,n){
                Node cur={a[i],g[i]};
                if(cur.x>q[len].x){
                    ans=max(ans,f[i]+q[len].y);
                    if(cur.y>q[len].y) q[++len]=cur;
                }
                else{
                    int k=lower_bound(q+1,q+len+1,cur)-q;
                    if(k>1) ans=max(q[k-1].y+f[i],ans);
                    else ans=max(ans,f[i]);
                    if(cur.x==q[k].x&&cur.y<q[k].y) continue;
                    if(cur.x<q[k].x&&cur.y<q[k].y) continue;
                    q[k]=cur;
                }
                //cout<<i<<" "<<ans<<endl;
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    /**
    题意:
    给定一个长度为n的序列,求随便去掉一段后(可以不去),序列的最长连续递增子序列长度。
    这题我先按紫书上的思路写的,那个思路的正确性是显然的,但是需要用set,在这种二元组中
    用set是非常恶心的,很容易出错,因此我写挂了。后来换了另一种思路,直接按照lis的
    写法,调了一下细节就过了。
    
    思路:
    先分别预处理出以a[i]为开头和结尾的连续子序列长度f[i]和g[i],
    接着按照基本的思路,枚举f[i],快速找到符合条件且最优的g[j],然后更新答案,将a[i],g[i]添加进去。
    由于无法划窗,快速找到g[i]就二分了,那么这个时候自然就会想到lis的nlogn算法,更新状态直接替代就行了。
    如何二分呢?当然是要看符合的条件和最优的单调性了,符合条件是指a[j]<a[i],最优就是
    在符合条件的前提下使得g[i]尽可能大。
    这里需要保持lis的单调性,如何保持单调性呢?这个思考过程我使用分类讨论的(智商太低无法一眼看出),
    二分找到第一个>=cur的q[k],根据a和g的大小关系总共6种情况(等于也算),以此来确定是否应该用cur将k替换。
    
    */
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    vue 设置请求超时时间处理
    element 表格只展开一行(点击下一行上一行关闭)
    element菜单刷新后定位问题?
    自己觉得不错的滚动条样式
    $.ajax()方法详解
    安卓获取自有证书的SHA1码
    sortable.js 拖拽排序及配置项说明
    uni-app 引入本地iconfont的正确姿势以及阿里图标引入
    mui slider禁止滑动
    stl源码剖析 详细学习笔记 仿函数
  • 原文地址:https://www.cnblogs.com/--560/p/5036452.html
Copyright © 2020-2023  润新知