题解:AT_abc360_g [ABC360G] Suitable Edit for LIS
RainRecall · · 题解
开幕先致敬一下经典:
时隔高达
感觉和 E 差不多难吧,虽然我赛时没做。
这种题先求两个东西,就是以
然后考虑枚举修改第
然后对于每个
以及,直接做是
然而,普通的实现方式需要进行复杂的离散化,且可能需要多判断一些东西,所以我们可以用 unordered_map 充当树状数组,不离散化直接做。然后再分析一下这样做的复杂度:
时间复杂度:如果你把 unordered_map 的复杂度视为常数的话,时间复杂度是
空间复杂度:每次最多在哈希表上多产生
综上,这种算法可以通过本题。
#include<bits/stdc++.h>
#define N 200005
using namespace std;
const int inf=1e9+7;
unordered_map<int,int>c;
int n,a[N],l[N],r[N],ans;
void add(int x,int k){
while(x<=inf){
c[x]=max(c[x],k);x+=x&-x;
}
}
int ask(int x){
int ans=0;
while(x){
ans=max(ans,c[x]);x-=x&-x;
}
return ans;
}
signed main(){
cin>>n;
for(int i=1;i<=n;++i)cin>>a[i];
for(int i=1;i<=n;++i){
r[i]=ask(a[i]-1)+1;
add(a[i],r[i]);
ans=max(ans,r[i]+(i!=n));
}
c.clear();
for(int i=n;i>=1;--i){
l[i]=ask(inf-a[i]-1)+1;
add(inf-a[i],l[i]);
ans=max(ans,l[i]+(i!=1));
}
c.clear();
for(int i=1;i<=n;++i){
int k=ask(a[i+1]);
ans=max(ans,l[i+1]+k+1);
add(a[i]+2,r[i]);
}
cout<<ans;
return 0;
}