zoukankan      html  css  js  c++  java
  • [bzoj 3048] [Usaco2013 Jan]Cow Lineup

    [bzoj 3048] [Usaco2013 Jan]Cow Lineup

    Description

    给你一个长度为n(1<=n<=100,000)的自然数数列,其中每一个数都小于等于10亿,现在给你一个k,表示你最多可以删去k类数。数列中相同的数字被称为一类数。设该数列中满足所有的数字相等的连续子序列被叫做完美序列,你的任务就是通过删数使得该数列中的最长完美序列尽量长。

    Input

    • Line 1: Two space-separated integers: N and K.
    • Lines 2..1+N: Line i+1 contains the breed ID B(i).

    Output

    • Line 1: The largest size of a contiguous block of cows with identical breed IDs that FJ can create.

    由于每个数都有10亿那么大,所以我们需要先离散化.之后我们维护一个队列.(好吧如果它也可以叫做单调队列)我们需要维护这个队列中不同数的个数<=k. 整个数列中的答案就可能是这个队列中某类数的出现次数.我们最多到k+1个数的时候就需要将队头像右移.答案其实等价于队列中有k+1类数,删除k类数留下来的同一类数的个数,那么显然队列中的每一类数的个数都有可能成为答案,所以我们在队列中就可以维护最大答案了.

    贴上代码

    #include <map>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    static const int maxm=1e6+10;
    
    int A[maxm],Q[maxm],cnt[maxm];
    int n,k,x,pos=1,head=1,tail=1,tot,kind,ans;
    
    map<int,int>M;
    
    int main(){
    	scanf("%d%d",&n,&k);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&x);
    		if(!M[x])M[x]=++tot;
    		A[i]=M[x];
    	}
    	
    	while(pos<=n){
    		while(head<=tail&&kind<=k&&pos<=n){
    			if(!cnt[A[pos]])kind++;
    			cnt[A[pos]]++;
    			ans=max(ans,cnt[A[pos]]);
    			Q[tail++]=A[pos++];
    		}
    		while(head<=tail&&kind==k+1&&pos<=n){
    			if(!cnt[A[pos]])break;
    			cnt[A[pos]]++;
    			ans=max(ans,cnt[A[pos]]);
    			Q[tail++]=A[pos++];
    		}
    		if(!--cnt[Q[head++]])kind--;
    	}
    	
    	printf("%d
    ",ans);
    
    	return 0;
    }
    

    传送门(bzoj权限题,附上另一OJ)

    P.S:由于我提交的OJ的数据似乎有些问题,所以代码只是与标程对拍了,如果有误,欢迎指正

  • 相关阅读:
    C#多线程学习笔记(三)——线程池
    html解析工具
    怎么样获取手机的主题
    我改进的《豆瓣搜》前后对比及源代码
    【收藏】Silverlight Style (二) 自定义样式在后台代码中应用
    C#多线程学习笔记(一)
    学习Linux——学习正确的思考方式(转)
    电信禁路由上网的破解方法
    印度软件业
    中国与印度软件工程师之比较
  • 原文地址:https://www.cnblogs.com/Exbilar/p/6817950.html
Copyright © 2011-2022 走看看