ZOJ3790_Consecutive Blocks
给出一个数组,最多可以删除k个数,问能够获得的最长的一个数字连续段为多少?
把所有相同的数字都提取出来,保存取得每个数字需要删除的数字,然后二分枚举就可以了。
召唤代码君:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #define maxn 500200 using 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; }
如有转载,请注明出处(http://www.cnblogs.com/lochan)