SP23776 KQUERYO - K-Query Online
题意
给定序列
做法
先考虑弱化版,离线算法。离线可以考虑莫队加值域分块,复杂度是
由于强制在线,这种做法不可行。一种做法是可持久化线段树,另一种是分块。
可以考虑块内二分,每个块 upper_bound
找
这种做法的复杂度是
所以最好略微卡常一下。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int N = 1e5 + 5;
int n, m, len;
#define Get(x) (int)(x / len + 1)
#define L(x) (int)((x - 1) * len)
int a[N];
vector<int> p[N];
int lans = 0;
int main()
{
scanf("%d", &n);
len = max(1, (int)sqrt(n));
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
p[Get(i)].push_back(a[i]);
}
for (int i = 1; i <= Get(n); i++) sort(p[i].begin(), p[i].end());
scanf("%d", &m);
while (m--)
{
int l, r, k;
scanf("%d%d%d", &l, &r, &k);
l ^= lans;
r ^= lans;
k ^= lans;
if (l < 1) l = 1;
if (r > n) r = n;
lans = 0;
//printf("%d %d %d\n", l, r, k);
if (l > r)
{
printf("0\n");
continue;
}
if (Get(l) == Get(r))
{
for (int i = l; i <= r; i++) lans += a[i] > k;
}
else
{
int lp = Get(l) + 1, rp = Get(r) - 1;
int lk = L(lp) - 1, rk = L(Get(r));
for (int i = lp; i <= rp; i++)
{
lans += p[i].end() - 1 - upper_bound(p[i].begin(), p[i].end(), k) + 1;
}
for (int i = l; i <= lk; i++) lans += a[i] > k;
for (int i = rk; i <= r; i++) lans += a[i] > k;
}
printf("%d\n", lans);
}
return 0;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现