HDU5489 Removed Interval (LIS+分治)
对于这类问题需要掌握nlog求解最长上升子序列的问题
我们发现可以枚举l后的每个点作为删除后的上升子序列的起点。
因为最后的答案肯定以某个点作为起点,因此我们枚举完就能知道答案
因此我们在删除前的一段中二分找到这个点所在的位置,前后相加-1就是当前的答案
对于所有答案取max即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=1e5+10; int a[N],b[N],f[N]; int s[N]; int main(){ ios::sync_with_stdio(false); int i; int t; cin>>t; int cnt=0; while(t--){ int n,l; cnt++; cin>>n>>l; int i; for(i=0;i<n;i++) cin>>a[i]; memset(s,0x7f,sizeof s); for(i=0;i<n;i++) b[i]=-a[i]; for(i=n-1;i>=l;i--){ int x=lower_bound(s,s+n,b[i])-s; s[x]=b[i]; f[i]=x+1; } memset(s,0x7f,sizeof s); int ans=0; int tmp=0; for(i=l;i<n;i++){ int x=lower_bound(s,s+n,a[i])-s; ans=max(ans,f[i]+x); x=lower_bound(s,s+n,a[i-l])-s; s[x]=a[i-l]; tmp=max(tmp,x+1); } ans=max(ans,tmp); cout<<"Case #"<<cnt<<": "<<ans<<endl; } return 0; }
没有人不辛苦,只有人不喊疼