先求求后面的最小值前缀,也就是预处理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\n",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\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; }
#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; }