1 条题解

  • 0
    @ 2025-5-28 20:56:02

    纯暴力(45 分)

    #include <bits/stdc++.h>
    using namespace std;
    int n, m;
    int a[1000000 + 5];
    bool flag[2005]; // 记录每位画家的画是否出现过
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        int ansL, ansR;
        ansL = 1, ansR = n;
        for (int l = 1; l <= n; l++)
        {
            // 一开始每位画家的画都没出现过
            for (int i = 1; i <= m; i++)
                flag[i] = false;
            for (int r = l; r <= n; r++)
            {
                // a[r] 这幅画对应的画家现在出现了
                flag[a[r]] = true;
                // 统计有几个画家的画出现过
                int cnt = 0;
                for (int i = 1; i <= m; i++)
                    if (flag[i])
                        cnt++;
                // 检验 a[l]~a[r] 是否包含了所有 m 位画家
                if (cnt == m)
                {
                    // a[l]~a[r] 合法
                    if (r - l + 1 < ansR - ansL + 1 ||
                        r - l + 1 == ansR - ansL + 1 && l < ansL)
                        ansL = l, ansR = r;
                    // a[l]~a[r] 已经合法了,后面的就不用看了
                    break;
                }
            }
        }
        cout << ansL << ' ' << ansR;
        return 0;
    }
    
    

    加一点小优化(90 分)

    #include <bits/stdc++.h>
    using namespace std;
    int n, m;
    int a[1000000 + 5];
    int flag[2005]; // 记录每位画家的画出现了几次
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        int ansL, ansR;
        ansL = 1, ansR = n;
        for (int l = 1; l <= n; l++)
        {
            // 一开始每位画家的画都没出现过
            for (int i = 1; i <= m; i++)
                flag[i] = 0;
            int cnt = 0; // l~r 出现的画家数量
            for (int r = l; r <= n; r++)
            {
                // a[r] 这幅画对应的画家现在出现了
                flag[a[r]]++;
                // 统计有几个画家的画出现过
                if (flag[a[r]] == 1)
                    cnt++;
                // 检验 a[l]~a[r] 是否包含了所有 m 位画家
                if (cnt == m)
                {
                    // a[l]~a[r] 合法
                    if (r - l + 1 < ansR - ansL + 1 ||
                        r - l + 1 == ansR - ansL + 1 && l < ansL)
                        ansL = l, ansR = r;
                    // a[l]~a[r] 已经合法了,后面的就不用看了
                    break;
                }
            }
        }
        cout << ansL << ' ' << ansR;
        return 0;
    }
    

    满分

    #include <bits/stdc++.h>
    using namespace std;
    int n, m;
    int a[1000000 + 5];
    int flag[2005]; // 记录每位画家的画出现了几次
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        int ansL, ansR;
        ansL = 1, ansR = n;
        // 一开始只有第一幅画
        for (int i = 1; i <= m; i++)
            flag[i] = 0;
        flag[a[1]] = 1;
        int cnt = 1;
        for (int l = 1, r = 1; l <= n; l++)
        {
            // 只要还没凑齐 m 幅画且 r 后面还有画,就把后面的画融入进来
            while (cnt != m && r < n)
            {
                r++;
                flag[a[r]]++;
                if (flag[a[r]] == 1)
                    cnt++;
            }
            // 如果当前凑齐了,尝试更新答案
            if (cnt == m)
            {
                // a[l]~a[r] 合法
                if (r - l + 1 < ansR - ansL + 1 ||
                    r - l + 1 == ansR - ansL + 1 && l < ansL)
                    ansL = l, ansR = r;
                // a[l]~a[r] 已经合法了,后面的就不用看了
            }
            // 接下来要处理 l+1 的情况了,把 a[l] 从方案中去掉
            flag[a[l]]--; // a[l] 这幅画对应的画家的画数减少一幅
            if (flag[a[l]] == 0)
                cnt--;
        }
        cout << ansL << ' ' << ansR;
        return 0;
    }
    

    信息

    ID
    2431
    时间
    1000ms
    内存
    128MiB
    难度
    3
    标签
    递交数
    12
    已通过
    4
    上传者