#P1563. 最长不下降序列.树状数组优化.填空题
最长不下降序列.树状数组优化.填空题
题目描述
设有由 个 (可能有相同) 的整数组成的数列,记为: {、、...、} 。
例如 {3,18,7,14,10,12,23,41,16,24}。若存在 且有 则称为长度为 的不下降子序列。
如上例中 {3,18,23,24} 就是一个长度为 的上升序列,同时也是 {3,7,10,12,16,24} 长度为 的不下降子序列。
程序要求,当原数列给出之后,求出最长的不下降子序列的长度。
输入格式
第一行为 ,表示 个数()
第二行 个整数,数值之间用一个空格分隔()
输出格式
一个整数,代表最长不下降子序列的长度。
数据样例
3
1 2 3
3
7
1 3 7 7 11 8 10
5
题目分析
朴素的思想是:
,通过要求每一个
for(int i=1;i<=n;i++){
dp[i] = 1;
for(int j=1; j<i ;j++){
if(a[j]<=a[i])
dp[i] = max(dp[i], dp[j]+1)
}
ans = max(ans, dp[i]);
}
这个算法的时间复杂度为 O(),而本题的 最大可能到 ,因此,O() 就一定超时了。
可以基于树状数组,找到 i 前面的 dp[j] 最大值。找最大值的时候,要满足几个条件:
- j 一定是在 i 前面( i<j )
- a[j] <= a[i]
- 找 dp[j] 的最大值要效率高
完善程序
#include<bits/stdc++.h>
using namespace std;
#define lowbit(i) ((-i)&i)
int n,c[100001],ans,dp[100001];
struct Num{
int num,pos;
bool operator < (const Num &other ) const {
return this->num<other.num ||(this->num==other.num && this->pos __填空(1)__ other.pos);
}
}a[100001];
int query(int x){ // 查询 c[1] 到 c[x] 的最大值
int ret = 0;
for(int i=x;i>0;i-=lowbit(i))
if(ret < c[i]) __填空(2)__;
return ret;
}
void update(int x,int k){ // 从 x 未知开始,刷新所有管理单元的信息(树状数组单元里存的是最大值)
for(int i=x;i<=n;i+=lowbit(i)){
if(c[i]<k) __填空(3)__;
else __填空(4)__;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i].num);
a[i].pos = i;
}
sort(a+1,a+1+n);
for(int i=1;i<=n;i++){
dp[i] = __填空(5)__;
ans = max(ans,dp[i]);
update(__填空(6)__);
}
cout<<ans;
return 0;
}
填空(1):{{ input(1) }}
填空(2):{{ input(2) }}
填空(3):{{ input(3) }}
填空(4):{{ input(4) }}
填空(5):{{ input(5) }}
填空(6):{{ input(6) }}