码迷,mamicode.com
首页 > 其他好文 > 详细

逛画展(双指针)

时间:2021-03-01 13:57:13      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:数据   while   main   记录   单位   必须   cst   代码   序列   

题意

博览馆正在展出由世上最佳的 \(M\) 位画家所画的\(N\)幅图画。可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必须说明两个数字,\(a\)\(b\),代表他要看展览中的第 \(a\) 幅至第 \(b\) 幅画(包含 \(a\)\(b\))之间的所有图画,而门票的价钱就是一张图画一元。

为了看到更多名师的画,你希望入场后可以看到所有名师的图画(至少各一张)。可是你又想节省金钱。。。

请你写一个程序决定购买门票时的 \(a\) 值和 \(b\) 值。数据保证有解,如果存在多个解,则输出 \(a\) 最小的那个解。

数据范围

\(1 \leq N \leq 1000000\)

\(1 \leq M \leq 2000\)

思路

很明显的双指针,就是右指针每往前推进一个单位,左指针指向的元素如果在这段序列中出现了不止\(1\)次,那么左指针可以往前推进。

序列中每个画家有几幅作品可以通过维护一个数组实现。

判断是否满足条件,可以记录一个\(sum\),新出现一个画家,那么\(sum + 1\)。当\(sum = m\)时,说明满足条件了。

序列中作品的数量可以用左右指针的距离来判断。

代码

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 1000010, M = 2010;

int n, m;
int a[N], q[N];
int cnt[M];

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
    int hh = 0, tt = -1;
    int l = 1, r = n;
    int sum = 0;
    for(int i = 1; i <= n; i ++) {
        if(!cnt[a[i]]) sum ++;
        cnt[a[i]] ++;
        while(tt >= hh && cnt[a[q[hh]]] >= 2) {
            cnt[a[q[hh]]] --;
            hh ++;
        }
        q[++ tt] = i;
        if(sum == m && q[tt] - q[hh] < r - l) {
            l = q[hh], r = q[tt];
        }
    }
    printf("%d %d\n", l, r);
    return 0;
}

逛画展(双指针)

标签:数据   while   main   记录   单位   必须   cst   代码   序列   

原文地址:https://www.cnblogs.com/miraclepbc/p/14459485.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!