HZAU 1205 Sequence Number(最大值前后缀 +双指针 + 二分)

来源:互联网 发布:阿里云 虚拟主机 jsp 编辑:程序博客网 时间:2024/06/05 02:05




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

#include <bits/stdc++.h>using namespace std;#define MAXN (100000+5)#define INF 0x3f3f3f3fint 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\n",res);    }   return 0;}


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

#include <bits/stdc++.h>using namespace std;#define MAXN (100000+5)#define INF 0x3f3f3f3fint 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\n",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\n",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\n", ans);    }    return 0;}


1 0
原创粉丝点击