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