题意:长度为n的序列a.每个数都不相同.
找到一个序列b 0<=b[i]<n.并且序列b满足: A[b[0]]> A[b[1]]> ...A[b[k]].
并且:A[j]<A[b[i+1]]. (min(b[i],b[i+1]) <j <max(b[i],b[i+1]))
n<=5e4,a[i]<=1e9 问序列b的长度最长为?
a[b[i]]要大于(a[b[i]]~a[b[i-1]])之间的数.
选下一个数,可以在上一个数的左右两边 而且不知道要选哪一个 不好处理.
先保存每个数的下标 然后将序列按照权值从大到小排序.
设dp[i]为以排序后下标i结尾 选出最长序列的长度.
因为j<i a[j]>a[i] 如果 b[j]~b[i]之间没有出现以前出现过的下标则.
dp[i]=max(dp[i],dp[j]+1) O(n^2 logn).
..1.11. X..1..1...
对于某个下标编号为X 其实它只能跟在X左边第一比它大的和X往右第一个比它大的后面.
找到一个序列b 0<=b[i]<n.并且序列b满足: A[b[0]]> A[b[1]]> ...A[b[k]].
并且:A[j]<A[b[i+1]]. (min(b[i],b[i+1]) <j <max(b[i],b[i+1]))
n<=5e4,a[i]<=1e9 问序列b的长度最长为?
a[b[i]]要大于(a[b[i]]~a[b[i-1]])之间的数.
选下一个数,可以在上一个数的左右两边 而且不知道要选哪一个 不好处理.
先保存每个数的下标 然后将序列按照权值从大到小排序.
设dp[i]为以排序后下标i结尾 选出最长序列的长度.
因为j<i a[j]>a[i] 如果 b[j]~b[i]之间没有出现以前出现过的下标则.
dp[i]=max(dp[i],dp[j]+1) O(n^2 logn).
..1.11. X..1..1...
对于某个下标编号为X 其实它只能跟在X左边第一比它大的和X往右第一个比它大的后面.
用单调栈预处理后 在DP一次即可 O(N+NlogN).
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e4+5;
struct node{
int x,id;
}a[N];
bool cmp(node a,node b)
{
return a.x>b.x;
}
int n,dp[N],c[N];
int le[N],rg[N];
stack<int> s;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].x,a[i].id=i;
while(!s.empty()&&a[s.top()].x<a[i].x)
rg[s.top()]=i,s.pop();
if(!s.empty())
le[i]=s.top();
s.push(i);
}
sort(a+1,a+1+n,cmp);
int res=1;
for(int i=1;i<=n;i++)
{
int j=a[i].id,x=le[j],y=rg[j];
dp[j]=1;
if(x)
dp[j]=max(dp[j],dp[x]+1);
if(y)
dp[j]=max(dp[j],dp[y]+1);
res=max(res,dp[j]);
}
printf("%d\n",res);
return 0;
}