洛谷P1638 逛画展

很经典的一道类似有一个头,一个尾,然后头和尾移动,从前往后扫一遍的题,我以前做过一道类似的,很相似,不过我不记得了,唉,可惜。正解是枚举区间的左右端点,右端点不断移动直到正好框住k种,此时,(r-l)与(j-i)比较,更新l,r,最后i++,直到i==n.

我一开始也没想到这样枚举,我想的是枚举框的长度,这样从小到大枚举,每次扫一遍判断是否包含k个,A4个点,剩下的都TLE了。。。

 

#include<bits/stdc++.h>
using namespace std;

int a[1000001],b[2001];
int n,m,l,r;

void Cin(int &x)
{
    char c=getchar();x=0;
    while(c<'0'||c>'9')c=getchar();
    while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar();
}


int main()
{
    Cin(n),Cin(m);
    r=0x7fffffff;
    for(int i=1;i<=n;i++) Cin(a[i]);
    for(int i=1,j=0,k=0;i<n;i++)
    {
        while(k<m&&j<n)
        {
            j++;
            if(j>n) break;
            if(b[a[j]]==0) k++;
            b[a[j]]++; 
        }
        if(k==m&&(r-l)>(j-i)) l=i,r=j;
        b[a[i]]--;
        if(b[a[i]]==0)k--;
    }
    cout<<l<<' '<<r;
}