P8776 最长不下降子序列 题解
Demeanor_Roy · · 题解
原题链接
不错的题,这里提供一个树状数组写法。
首先对于序列每一个位置,求出
接着考虑拼接。
首先我们可以得出一个结论:改变
那接下来就好做了,我们对每一个位置
温馨提示:因为要用三个树状数组,最好把树状数组写成类更方便。
update on 11.19: 之前有一点没有说清楚,其实这个做法隐含了一个贪心,那就是如果改变
update on 11.25: 代码有一点小锅,已修。
update on 2025.5.12: 代码又有一点小锅,已修。
下附代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,k,ans,val[N],L[N],R[N];
vector<int> vec;
struct BIT
{
int C[N];
inline void add(int x,int y){for(;x<=n+1;x+=x&-x) C[x]=max(C[x],y);}
inline int query(int x)
{
int ans=0;
for(;x;x-=x&-x) ans=max(ans,C[x]);
return ans;
}
}le,re,s;
int main()
{
scanf("%d%d",&n,&k);
val[0]=1;val[n+1]=n+1;
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
for(int i=1;i<=n;i++) vec.push_back(val[i]);
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
for(int i=1;i<=n;i++) val[i]=lower_bound(vec.begin(),vec.end(),val[i])-vec.begin()+1;
for(int i=1;i<=n;i++)
{
L[i]=le.query(val[i])+1;
le.add(val[i],L[i]);
}
for(int i=n;i>=1;i--)
{
R[i]=re.query(n-val[i]+1)+1;
re.add(n-val[i]+1,R[i]);
}
for(int i=k+1;i<=n+1;i++)
{
s.add(val[i-k-1],L[i-k-1]);
ans=max(ans,s.query(val[i])+k+R[i]);
}
printf("%d",ans);
return 0;
}
完结撒花~