首页 > 代码库 > ZOJ3790_Consecutive Blocks

ZOJ3790_Consecutive Blocks

给出一个数组,最多可以删除k个数,问能够获得的最长的一个数字连续段为多少?

把所有相同的数字都提取出来,保存取得每个数字需要删除的数字,然后二分枚举就可以了。

 

 

召唤代码君:

 

 

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#define maxn 500200using namespace std;int a[maxn],b[maxn],first[maxn],next[maxn];int Q[maxn],top,f[maxn];bool vis[maxn];int n,k,N,ans;void go(int cur){    vis[cur]=true;    if (next[cur]!=-1){        go(next[cur]);        Q[top++]=cur-next[cur]-1;    }    else Q[top++]=0;}int main(){    while (scanf("%d%d",&n,&k)!=EOF){        for (int i=0; i<n; i++){            scanf("%d",&a[i]);            b[i]=a[i];        }        sort(b,b+n);        N=unique(b,b+n)-b;        for (int i=0; i<n; i++) a[i]=lower_bound(b,b+N,a[i])-b+1;        memset(first,-1,sizeof(int)*(n+3));        for (int i=0; i<n; i++) next[i]=first[a[i]],first[a[i]]=i;        memset(vis,false,sizeof(bool)*(n+2));        ans=0;        for (int i=n-1; i>=0; i--)            if (!vis[i]){                top=0;                go(i);                for (int j=1; j<top; j++) Q[j]+=Q[j-1];                for (int pos=0; pos<top; pos++){                    if (Q[top-1]-Q[pos]<=k){                        ans=max(ans,top-pos);                        break;                    }                    int l=pos,r=top-1,mid;                    while (l<r){                        mid=(l+r+1)/2;                        if (Q[mid]-Q[pos]>k) r=mid-1;                            else l=mid;                    }                    ans=max(ans,l-pos+1);                }            }        printf("%d\n",ans);    }    return 0;}