[BZOJ3048][Usaco2013 Jan]Cow Lineup(单调队列)

题目描述

传送门

题解

首先离散化。
类似于单调队列的思想,一个头指针一个尾指针,向后移动的时候维护区间的种类数和它们的个数,保证区间种数-k=1。
边做边维护最大值。

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;

const int max_n=1e5+5;

int n,k,head,tail,kinds,Max;
int a[max_n],b[max_n],sum[max_n];
bool vis[max_n];

int main(){
// freopen("lineup.in","r",stdin);
// freopen("lineup.out","w",stdout); 
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;++i){
        scanf("%d",&a[i]);
        b[i]=a[i];
    }
    sort(b+1,b+n+1);
    int cnt=unique(b+1,b+n+1)-b-1;
    for (int i=1;i<=n;++i)
      a[i]=lower_bound(b+1,b+n+1,a[i])-b;

    head=1,tail=1;
    sum[a[1]]=1,kinds=1,vis[a[1]]=true;
    while (tail<n){
        while (vis[ a[tail+1] ]||(!vis[ a[tail+1] ]&&kinds-1<k)){
            tail++;
            if (!vis[ a[tail] ]){
                vis[ a[tail] ]=true;
                kinds++;
                sum[ a[tail] ]=1;
                Max=max(Max,sum[ a[tail] ]);
            }
            else{
                sum[ a[tail] ]++;
                Max=max(Max,sum[ a[tail] ]);
            }
            if (tail==n) break;
        }

        if (sum[ a[head] ]==1){
            kinds--;
            vis[ a[head] ]=false;
        }
        sum[ a[head] ]--;
        head++;
    }

    printf("%d\n",Max);
}

总结

你可能感兴趣的:([BZOJ3048][Usaco2013 Jan]Cow Lineup(单调队列))