2 条题解

  • 0
    @ 2025-7-16 19:53:39

    每个右端点调整到合适的左端点的双指针

    #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;
        // 一开始没有画
        int cnt = 0;
        for (int l = 1, r = 1; r <= n; r++)
        {
            // 当前的第 r 幅画是新加进来的
            flag[a[r]]++;
            if (flag[a[r]] == 1)
                cnt++;
            // 对于当前的右端点 r,把左端点 l 尽可能往右移
            while (flag[a[l]] > 1)
            {
                flag[a[l]]--;
                l++;
            }
            if (cnt == m)
            {
                if (r - l + 1 < ansR - ansL + 1 ||
                    r - l + 1 == ansR - ansL + 1 && l < ansL)
                    ansL = l, ansR = r;
            }
        }
        cout << ansL << " " << ansR << "\n";
        return 0;
    }
    
    
    • 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;
      }
      
      • 1

      信息

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