51nod 40 选择子序列 单调栈+DP
2017-12-30 20:02
197 查看
题意:长度为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往右第一个比它大的后面.
用单调栈预处理后 在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
;
bool cmp(node a,node b)
{
return a.x>b.x;
}
int n,dp
,c
;
int le
,rg
;
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];
4000
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;
}
找到一个序列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
;
bool cmp(node a,node b)
{
return a.x>b.x;
}
int n,dp
,c
;
int le
,rg
;
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];
4000
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;
}
相关文章推荐
- 51Nod - 1153 选择子序列 (单调栈+线段树)
- 51nod 40 序列分解 暴力dfs or 折半+字典树
- 51nod 1561 另一种括号序列 单调队列+hash+二分
- 51nod 1153 选择子序列 (好题)
- 51nod选择子序列:单调栈 & 分治
- 最长单调递增子序列
- 【bzoj1345】[Baltic2007]序列问题Sequence 单调栈
- CPC3——H.喵喵的最长序列(RMQ|单调队列)
- NYOJ-214 单调递增子序列(二) AC
- 长度不超过k的最大连续子序列(单调队列)
- 【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改区间查询
- 【LCS,LIS】最长公共子序列、单调递增最长子序列
- NYOJ-17 单调递增最长子序列
- 51Nod - 1215 数组的宽度 思维+单调栈
- Python3学习笔记03-基本数据类型、序列、运算及缩进和选择
- 51Nod-1780-完美序列
- 51Nod-1400-序列分解
- [51NOD]1126 求递推序列的第N项 [线性递推关系与矩阵乘法]
- NYOJ 17 (最长单调递增子序列) O (n*n) + O(n*lgn)
- 51nod 1158 全是1的最大子矩阵 单调栈