HDU5489 Removed Interval (LIS+分治)

对于这类问题需要掌握nlog求解最长上升子序列的问题

我们发现可以枚举l后的每个点作为删除后的上升子序列的起点。

因为最后的答案肯定以某个点作为起点,因此我们枚举完就能知道答案

因此我们在删除前的一段中二分找到这个点所在的位置,前后相加-1就是当前的答案

对于所有答案取max即可

#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;
}
View Code

 

posted @ 2021-03-06 22:00  朝暮不思  阅读(45)  评论(0编辑  收藏  举报