洛谷P1638

P1638 逛画展

最近再备赛蓝桥杯国赛

这是《深入浅出程序设计竞赛(进阶篇)》书里的第二题
一道非常典型的双指针求区间的题目

这本书放了很久,今天开始把这书例题都过一遍,学算法虽然总能很快听懂概念,但是做题的时候就是独立做不出来,如果我常规刷题的话,学习效率十分十分低下,所以我选用给答案写注释的方做一下试验

C++ 点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6+10;

int n, m, l, r;
vector<int> a(MAXN);
vector<int> sum(2010, 0);
int ans, ansl, ansr, num;

int main() {
    cin >> n >> m;//图画总数,画师总数
    for(int i = 1; i <= n; i++) {
        cin >> a[i];//图画对应画师编号
    }
    l = 1; r = 1; num = 0; ans = MAXN;

    //r指针是在测试当前区间未满足要求时往前走,l指针则在区间满足后前进以缩小区间范围,检验最前端图画是否可去,如不可去,则接着寻找最优解
    while(l <= r && r <= n + 1) {//左闭右开双指针
        if (num < m) {//rpre = r,a[l, rpre)区间画师数量未齐时
            r++;//右指针向右一步,区间变成[l, rpre + 1)
            sum[a[r - 1]]++;//rpre作品的画师出现次数+1;
            if (sum[a[r - 1]] == 1) num++;//当画师第一次出现时,区间画师数+1;
        } else {//找到了一个集齐画师的区间时
            if (ans > r - l) {//对比区间大小,新找到的区间更小时
                ans = r - l;//更新答案区间大小
                ansl = l;//更新答案区间左边界
                ansr = r - 1;//更新右边界
            }
            //左区间l向右走,测试l画去掉之后答案是否更优
            sum[a[l]]--;
            if (sum[a[l]] == 0) num--;
            l++;
        }
    }
    cout << ansl << ' ' << ansr << '\n';
    return 0;
}
posted @ 2025-05-08 21:54  Chuan81  阅读(15)  评论(0)    收藏  举报