• 洛谷 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;
    }
    
  • 相关阅读:
    win10开机时内存使用率达到99%以上
    https的基本原理,看完你的程序员女朋友再也不和你提分手了
    Tomcat样例安全漏洞
    Linux5355端口被0.0.0.0监听
    jQuery的ajax
    事件委托(事件代理)
    jQuery的事件绑定和解绑
    事件对象
    JS的事件流的概念(重点)
    jQuery的位置信息
  • 原文地址:https://www.cnblogs.com/acioi/p/11645626.html
Copyright © 2020-2023  润新知