洛谷 P1638 逛画展 题解

P1638 逛画展

题目描述

博览馆正在展出由世上最佳的 M 位画家所画的图画。

wangjy想到博览馆去看这几位大师的作品。

可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必须说明两个数字,

a和b,代表他要看展览中的第 a 幅至第 b 幅画(包含 a 和 b)之间的所有图画,而门票

的价钱就是一张图画一元。

为了看到更多名师的画,wangjy希望入场后可以看到所有名师的图画(至少各一张)。

可是他又想节省金钱。。。

作为wangjy的朋友,他请你写一个程序决定他购买门票时的 a 值和 b 值。

输入格式

第一行是 N 和 M,分别代表博览馆内的图画总数及这些图画是由多少位名师的画

所绘画的。

其后的一行包含 N 个数字,它们都介于 1 和 M 之间,代表该位名师的编号。

输出格式

a和 b(a<=b) 由一个空格符所隔开。

保证有解,如果多解,输出a最小的。

输入输出样例

输入 #1

12 5
2 5 3 1 3 2 4 1 1 5 4 3

输出 #1

2 7

说明/提示

约定 30%的数据N<=200 , M<=20

60%的数据N<=10000 , M<=1000

100%的数据N<=1000000 , M<=2000

【思路】

双指针
枚举起点a
终点b(尾指针)累加
直到可以看到每一位名师的画作
然后比较记录的区间长度
如果这个区间小那就a,b替代之前记录下来的

怎么判断每一位名师的画作是否被看过?
用一个桶,
如果这位名师的画作加入进来那就在他的桶上累加
如果是从0变为1的一个桶那就是新加入了一位画师
所以计数器累加(计数器用来计数目前可以看到画师画作的数量)
如果是一个从1变为0的桶
那就是少看到一位画师的画作
所以这个时候要计数器累减

【完整代码】

#include<iostream>
#include<cstdio>

using namespace std;
int l = 1,r = 1;
int acioi[1000006];
int tong[2020];
int js = 0;
int L,R,M = 0x7fffffff;

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(register int i = 1;i <= n;++ i)
        scanf("%d",&acioi[i]);
    tong[acioi[1]] ++;
    js ++;
    for(l = 1,r = 1;l <= n;++ l)
    {
        tong[acioi[l - 1]] --;
        if(tong[acioi[l - 1]] == 0)
            js --;
        while(js < m && r <= n)
        {
            ++r;
            tong[acioi[r]] ++;
            if(tong[acioi[r]] == 1)
                js ++;
        }
        if(js == m && r - l + 1 < M)
        {
            M = r - l + 1;
            L = l;R = r;
        }
    }
    cout << L << " " << R << endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/acioi/p/11645626.html