zoukankan      html  css  js  c++  java
  • HZAU 1205 Sequence Number(最大值前后缀 +双指针 + 二分)




    先求求后面的最小值前缀,也就是预处理1~i的最小值,然后从右往左双指针,维护右端点>左端点,如果右端点<1~L的最小值,则移动右端点。

    #include <bits/stdc++.h>
    using namespace std;
    #define MAXN (100000+5)
    #define INF 0x3f3f3f3f
    int n,k,arr[MAXN],mmin[MAXN];
    int main() {
        while(~scanf("%d",&n)){
            mmin[0]=INF;
            for(int i=1;i<=n;i++)
                scanf("%d",&arr[i]);
            for(int i=1;i<=n;i++)
                mmin[i]=min(mmin[i-1],arr[i]);
     
            int res=0;
            for(int l=n,r=n;l>=1;l--){
                while(mmin[l]>arr[r])
                    r--;
                res=max(res,r-l);
            }
            printf("%d
    ",res);
        }
       return 0;
    }


    下面闲的*疼又优化了一下,指针直接跳到最小值位置,然后再往下遍历,当然了复杂度还是O(n)

    #include <bits/stdc++.h>
    using namespace std;
    #define MAXN (100000+5)
    #define INF 0x3f3f3f3f
    int n,k,arr[MAXN],mmin[MAXN],mark[MAXN];
    int main() {
        while(~scanf("%d",&n)){
            mmin[0]=INF,mark[0] = 0;
            for(int i=1;i<=n;i++)
                scanf("%d",&arr[i]);
            for(int i=1;i<=n;i++)
                if(mmin[i-1]<arr[i])
                    mmin[i]=mmin[i-1] , mark[i] = mark[i-1];
                else
                    mmin[i] = arr[i] , mark[i] = i;
     
            int res=0;
            for(int l=n,r=n;l>=1;){
                // cout<<"l="<<l<<' '<<" r="<<r<<" res="<<res<<endl;
                while( mmin[mark[l]] > arr[r] )
                    r--;
                res=max(res,r-mark[l]);
                l=min(mark[l],--l);
                //cout<<"l="<<l<<' '<<" r="<<r<<" res="<<res<<endl<<endl;
            }
            printf("%d
    ",res);
        }
       return 0;
    }


    整理的时候看到网上还有用最大值后缀+二分的,也还可以

    这是一道排序可以过的题,也可以rmq+二分 最快的写法可以用单调栈做到O(n)

       我是求后面的最大值后缀,二分后缀;

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-4
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=1e5+10,M=1e6+10,inf=2147483647;
    const ll INF=1e18+10,mod=2147493647;
     
    int a[N],nex[N];
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            memset(nex,0,sizeof(nex));
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            for(int j=n;j>=1;j--)
                nex[j]=max(a[j],nex[j+1]);
            int ans=0;
            for(int i=1;i<=n;i++)
            {
                int s=i,e=n,pos=-1;
                while(s<=e)
                {
                    int mid=(s+e)>>1;
                    if(nex[mid]>=a[i])
                        pos=mid,s=mid+1;
                    else e=mid-1;
                }
                ans=max(ans,pos-i);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }



    最开始做DP做疯了,DP瞎搞,没脑子,都快O(n^2)复杂度了都,还不如暴力,ORZ...
    #include <bits/stdc++.h>
    using namespace std;
    
    #define MAXN (50000 + 10)
    
    struct Node {
        int i, a, dp;
    };
    
    struct cmp{
        bool operator()(const Node &a,const Node &b) {
                return a.dp-b.dp>0;
        }
    };
    
    int main()
    {
        int n, a;
        Node tmp;
    
        int ans;
        while (~scanf("%d", &n)) {
            set<Node, cmp> mySet;
    
            scanf("%d", &a);
            tmp.i=0,tmp.a = a,tmp.dp = 0;
            mySet.insert(tmp);
            ans = 0;
            for (int i = 1; i < n; ++i) {
                scanf("%d", &a);
                set<Node, cmp>::iterator it;
    
                for (it = mySet.begin(); it != mySet.end(); ++it)
                    if (a >= (*it).a)   break;
    
                tmp.i = i,tmp.a = a;
                if (it == mySet.end())
                    tmp.dp = 0;
                else
                    tmp.dp = i - (*it).i + (*it).dp;
    
                if (tmp.dp > ans)  ans = tmp.dp;
                mySet.insert(tmp);
            }
    
            printf("%d
    ", ans);
        }
    
    
        return 0;
    }
    


  • 相关阅读:
    apache配置虚拟主机及虚拟目录
    Apache的443端口被占用解决方法
    Windows下XDebug 手工配置与使用说明
    php中输入这个网站的网址跳转到你定义的页面代码
    XAMPP的使用说明
    Linux致命命令
    wget 命令用法详解
    Linux 关机命令详解
    LINUX视频教程下载地址
    ubuntu 开机自动开启数字小键盘
  • 原文地址:https://www.cnblogs.com/zswbky/p/6792891.html
Copyright © 2011-2022 走看看