标签:div put ble ems cin name out min 输入
题目:
某同学拿到一组数列 $ a_1, a_2, \cdots , a_n $,他想知道存在多少个区间 $ [l, r] $ 同时满足下列两个条件:
1. $ r - l + 1 = k $;
2. 在 $ a_l, a_{l + 1}, \cdots , a_r $ 中,存在一个数至少出现 t 次。
要求要做的就是输出满足条件的区间个数。
input
第一行输入三个整数 $ n, k, t (1 \leqslant n, k, t \leqslant 10^5)
第二行输入 n 个整数, $ a_1, a_2, \cdots, a_n(1 \leqslant a_i \leqslant 10^5) $
output
输出区间个数。
Example
input
5 3 2 3 1 1 1 2
output
3
hint
样例中,因为区间 $ [1, 3] $ 中 1 出现了 2 次,区间 $ [ 2, 4] $ 中 1 出现了 3 次, 区间 $ [3, 5] $ 中 1 出现了 2 次,所以一共有 3 个区间满足条件。
这是在群里看到的一个题,感觉应该是一个dp题,但由于我太渣,推半天转移方程推不出来。。。决定先写一个暴力的试试,然后再考虑dp。。。或者感觉可以维护一个区间树。。。
下面是一个暴力点的算法,不知道对不对。。
#include <iostream> #include <minmax.h> const int N = 100001; using namespace std; int main() { int n, k, t, c, dp; int a[N], b[N]; while (~scanf_s("%d %d %d", &n, &k, &t)) { dp = 0; memset(b, 0, sizeof(b)); for (int i = 0; i < n; i++) { cin >> a[i]; b[a[i]]++; dp = max(dp, b[a[i]]); } if (k == 1) cout << n << endl; else if (t == 1) cout << n - k + 1 << endl; else if (k == n) if (dp == t) cout << "1" << endl; else cout << "0" << endl; else { dp = 0; for (int j = 0; j < n - k + 1; j++) { c = 1; for (int i = j; i < k + j; i++) for (int l = i + 1; l < k + j; l++) if (a[i] == a[l]) { if (c == 1) b[0] = a[i]; c++; if (b[0] != a[i]) c--, b[0] = a[i]; if (c == t) { dp++, i = k + j; break; } } } cout << dp << endl; } } return 0; }
测试效果:
6 4 3 2 1 1 2 1 2 1 5 3 2 3 1 1 1 2 3 6 4 2 2 1 1 2 1 2 3 6 3 3 2 1 1 2 1 2 0 6 3 2 2 1 1 2 1 2 4 5 5 4 3 1 1 1 2 0 5 5 1 1 2 3 4 5 1 5 3 1 1 2 3 4 5 3 5 4 3 3 1 1 1 2 2
有空再考虑一下其他方法。
标签:div put ble ems cin name out min 输入
原文地址:https://www.cnblogs.com/darkchii/p/9602184.html