专栏文章
题解:P5978 [CEOI 2018] Global warming
P5978题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minack78
- 此快照首次捕获于
- 2025/12/01 23:09 3 个月前
- 此快照最后确认于
- 2025/12/01 23:09 3 个月前
假设你要找一个区间加上 ,则这个区间一定是数列的后缀。
证明是简单的,因为假设某个位置 位于最终的答案中且 属于被操作的那个区间,则后面的数显然越大越好。
于是我们可以直接枚举所加的后缀是什么,假设是 ,则我们只需要考虑位置 在这个后缀中的最长上升子序列,并加上该位置的数放到前缀里所能得到的最长上升子序列。
求最长上升子序列的过程是 的,则总时间复杂度 。
代码
CPP#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
const ll N=2e5+10;
ll a[N],f_pre[N],g_pre[N],n,V;
ll f_suf[N],g_suf[N];
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>V;for(ll i=1;i<=n;i++) cin>>a[i];
ll tot=1;
for(ll i=1;i<=n;i++){
if(i==1) f_pre[i]=1,g_pre[1]=a[i];
else{
ll pos=lower_bound(g_pre+1,g_pre+1+tot,a[i]+V)-g_pre;
f_pre[i]=pos;
pos=lower_bound(g_pre+1,g_pre+1+tot,a[i])-g_pre;
g_pre[pos]=a[i];
if(pos>=tot) tot=pos;
}
}
tot=1;
for(ll i=n;i>=1;i--){
if(i==n) f_suf[i]=1,g_suf[1]=-a[i];
else{
ll pos=lower_bound(g_suf+1,g_suf+1+tot,-a[i])-g_suf;
f_suf[i]=pos;
g_suf[pos]=-a[i];
if(pos>=tot) tot=pos;
}
}
ll ans=0;
for(ll i=1;i<=n;i++) ans=max(ans,f_pre[i]+f_suf[i]-1);
cout<<ans;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...