牛客多校第五场 K King of Range
题意:
给定一个个数得序列,给定个询问,每次给出一个,寻找有多少个区间中最大值与最小值之差严格大于。
思路:
可以发现,如果已经知道一个区间最大值与最小值严格大于k之后,那么我们便可以往从两头这个区间随意加数并且会对答案有贡献:
如果加一个比最大值大的或者比最小值小的数,那么这个区间差值还是严格大于;
如果加一个介于最大值最小值之间的数,那么这个区间差值不会发生变化。
那么发现这一点之后便可以使用双指针寻找区间了,那么怎么维护区间最值呢(比赛的时候想到了用双指针但没想到怎么维护最值),表就派上用场了,那么我们固定一个,让去寻找即可,找到第一个合适的区间就可以停下了,那么j往后的所有数都可以加到这个区间中而对答案产生贡献就是。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1E5 + 10, M = 18;
int n, m, k;
int w[N];
int f1[N][M], f2[N][M];
int lg[N];
void init() {
for (int j = 0; j < M; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
if (!j) f1[i][j] = w[i], f2[i][j] = w[i];
else {
f1[i][j] = max(f1[i][j - 1], f1[i + (1 << j - 1)][j - 1]);
f2[i][j] = min(f2[i][j - 1], f2[i + (1 << j - 1)][j - 1]);
}
}
}
}
bool check(int l, int r, int k) {
int len = r - l + 1;
int d = lg[len];
int maxD = max(f1[l][d], f1[r - (1 << d) + 1][d]);
int minD = min(f2[l][d], f2[r - (1 << d) + 1][d]);
return maxD - minD > k;
}
int main() {
//ios::sync_with_stdio(false); cin.tie(0);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &w[i]);
lg[2] = 1;
for(int i=3;i<=n;i++) {
lg[i] = lg[i / 2] + 1;
}
init();
while (m--) {
long long res = 0;
int k; scanf("%d", &k);
for (int l = 1, r = 1; l <= n; l++) {
while (!check(l, r, k) && r <= n && l <= r) r++;
if (r <= n) res += n - r + 1;
}
printf("%lld\n", res);
}
return 0;
}
值得一提的是,用库函数函数的效率有点不行,会被卡,所以还是乖乖预处理一个数组吧。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端