洛谷P1638 逛画展

题意

给n和m

个数为n的数组,内容是1~m之间的数字,求最小的包含1~m(至少出现过一次)l,r(如果有相同的区间长度,l要最小)

思路

先第一步,找到右边   r(至少出现过一次)的值,然后将l从1 开始到r,无用的重复的删除,初次确认L=l,R=r

(因为没有想到第二步一直只有45分)

第二步,在  r  右移动,判断 vis[a[l]] 的值是否大于1,大于一就减,l右移

举个例子

6 3

1 2 2 3 2 1

如果没有第二步骤答案就是1 4

正确答案就是4 6

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 998244353
const int maxn=1e6+10;
int n,k;
int a[maxn],vis[2100]={0};
int main() {
    scanf("%d%d",&n,&k);
    for(it i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    int sum=0,l,r,zl,zr;
    for(it i=1;i<=n;i++){
        if(vis[a[i]]==0){sum++;}vis[a[i]]++;
        if(sum==k){r=i;break;}
    }
    for(it i=1;i<=r;i++){
        vis[a[i]]--;if(vis[a[i]]==0){vis[a[i]]++;l=i;break;}
    }
    zl=l,zr=r;
    for(it i=r+1;i<=n;i++){
        vis[a[i]]++;r++;
        while(vis[a[l]]>1){
            vis[a[l++]]--;
        }
        if(r-l<zr-zl){
            zr=r;zl=l;
        }
    }
    printf("%d %d\n",zl,zr);
    return 0;
}

 

posted @ 2020-02-12 14:48  ouluy  阅读(132)  评论(0编辑  收藏  举报