#include <bits/stdc++.h>
using namespace std;
int n, m;
int a[1000100];
int b[1000100];
int ans = 2e9 + 1;
int rr, ll;
int ct;
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int j = 1;
for (int i = 1; i <= n; i++) {
b[a[i]]++;
if (b[a[i]] == 1)
ct++;
if (ct == m) {
while (j < i && b[a[j]] >= 2) {
b[a[j]]--;
j++;
}
if (i - j + 1 < ans) {
ans = i - j + 1;
rr = i;
ll = j;
}
b[a[j]]--;
ct--;
j++;
}
}
cout << ll << " " << rr;
}
本以为是一道水题,没想到调了这么久emmm。
首先一开始 想的是从两头枚举, 直到一端枚举完,在枚举另一端
但仔细想想就不对啦 比如 12222211111 ,明显答案是 中间那个2 1
如果从两头枚举会把1 给 枚举掉,肯定错了
——————————————————————————————————
所以就知道了正确的枚举,每次将一个画,加入b中,如果没看过就ct++;
当ct == m 时 ,就可以从左端开始减去 画画的数量,很显然只有2及2以上的画可以去掉,
移动玩 i 后 比大小统计答案。
然后这个地方很重要 (之前一直没在意)由于比完后是相当于 右指针 在 前j 个位置所能达到的最理想情况, 所以 要将 i 再后移一位,去找下面的情况
#include <bits/stdc++.h>
using namespace std;
int n, m;
int a[1000100];
int b[1000100];
int ans = 2e9 + 1;
int rr, ll;
int ct;
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int j = 0;//因为下面的原因所以决定从0开始
for (int i = 1; i <= n ; i++ ) {
while (j <= n && ct < m) {
j++;//先得保证每次j都得产生位移,不然下一次会在重复的地方多算一次
if (b[a[j]] == 0)
ct++;
b[a[j]]++;
}
if (j <= n && j - i + 1 < ans) {
rr = j, ll = i;
ans = j - i + 1;
}
b[a[i]]--;//将第i个画减去
if (b[a[i]] == 0)
ct--;
}
cout << ll << " " << rr;
}
第一个答案是属于先一个个枚举每幅画,ct == m 时再从左端开始减去
第二个答案是属于先让 ct == m ,然后从末尾开始枚举 减去一幅画