前缀和brz的雪糕
解题思路
用前缀和数组解题, t b [ i ] tb[i] tb[i] 保存从起始位置到第 i i i 个位置的愉悦值。这里讲思路的时候默认位置从 1 1 1 开始。
查询的时候,假设区间是 [ a , b ] [a, b] [a,b],分两种情况:
-
a = 1 a=1 a=1。值直接为 t b [ b ] tb[b] tb[b]。
-
a > = 2 a >= 2 a>=2。这时候要进行判断了,一般情况下值直接是 t b [ b ] − t b [ a − 1 ] tb[b] - tb[a - 1] tb[b]−tb[a−1](等价于 t b [ b ] − t b [ a ] + 1 tb[b] - tb[a] + 1 tb[b]−tb[a]+1) 。
但有个特殊情况: t b [ a ] = t b [ a − 1 ] tb[a]=tb[a-1] tb[a]=tb[a−1],也就是说 a a a 位置和 a − 1 a-1 a−1 位置的数是一样的,之前处理前缀和的时候位置 a a a 相当于没有加 1 1 1。
但是现在 a a a 位置变成了第一个位置的数,需要加 1 1 1,那就相当于现在少加了个 1 1 1,所以这种时候值在原来的基础上加 1 1 1 即可。
参考代码
写的时候数组下标从 0 0 0 开始的,与题给区间要记得转换一下(如 a a a 对应数组中的下标 a − 1 a-1 a−1 )。
#include<bits/stdc++.h>
using namespace std;
//#define LOCAL //提交的时候一定注释
#define _for(i, a, b) for(int i = (a); i < (b); ++i)
#define _rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define pb push_back
#define VI vector<int>
//#define maxn 1e2+10
#define INF 0x3f3f3f3f
#define mp make_pair
typedef long long LL;
typedef double db;
const double eps = 1e-6; //定义浮点数误差
const int MOD = 998244353;
const int maxn = 2000010;
int readint(){
int x; scanf("%d", &x); return x;
}
int tb[maxn];
int main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int n, k, q;
scanf("%d%d%d", &n, &k, &q);
VI x;
_for(i, 0, n) {
x.pb(readint());
}
int pre = 1;
tb[0] = pre;
_for(j, 1, x.size()) {
pre += (x[j] != x[j - 1]) ? 1 : 0;
tb[j] = pre; //处理前缀和数组
}
_for(i, 0, q) {
int sum, a, b;
scanf("%d%d", &a, &b);
if (a - 2 >= 0) {
sum = tb[b - 1] - tb[a - 2];
if (x[a - 1] == x[a - 2]) sum++;
}
else //a = 1的时候,直接取tb的值
sum = tb[b - 1];
printf("%s\n", (sum >= k) ? "Yes" : "No");
}
return 0;
}