当前位置: 首页 > news >正文

二维数点问题 1

二维数点问题

例题 1

给定一个长为 nnn 的序列 aaa,有 mmm 次询问,每次询问给定 l,r,xl,r,xl,r,x,求 [l,r][l,r][l,r] 区间中小于等于 xxx 的数的个数。

数据范围:1≤n,m,ai,l,r,x≤2×1061 \le n,m,a_i,l,r,x\le 2\times 10^61n,m,ai,l,r,x2×106

题解

我们需要求出 l≤i≤rl\le i\le rlir 中,有多少个数小于等于 xxx,这里有 两个偏序关系 ≤\le≥\ge

将两个偏序关系减少至一个,就变成求出 i≤ri\le rir 有多少个数小于等于 xxx、求出 i≤l−1i\le l-1il1 有多少个数小于等于 xxx

将二者求出来的结果 作差 就得到了原需求。

所以目标转化为实现 i≤ki\le kik 有多少个数小于等于 xxx

我们将所有的询问都转为形如 (pos,x)(pos,x)(pos,x) 的二元组,并将其按 pospospos 排序。

1∼n1\sim n1n 开始遍历原序列,并维护一个权值树状数组,对于 a[i]a[i]a[i],单点插入树状数组中即可。

然后求 i≤posi\le posipos 有多少个数小于等于 xxx,就可以查询此时树状数组的 1∼x1\sim x1x 的前缀和。

现在我们求出了每一对二元组 (pos,x)(pos,x)(pos,x) 对应的答案,但是如何重组为 (l,r,x)(l,r,x)(l,r,x) 对应的答案呢?

有些题目可能会卡常,所以不能用 mapmapmap

可以考虑一个结构体 nodenodenode

struct node {int pos;int x;int id;int op;
};

nodenodenode 结构体是用来存放每一个询问的信息,其中的 ididid 表示是第几次询问,其中 opopop 表示符号。

因为一次询问 (l,r,x)(l,r,x)(l,r,x) 会被拆分为两个二元组 (l−1,x)(l-1,x)(l1,x)(r,x)(r,x)(r,x)

我们令 (l−1,x)(l-1,x)(l1,x)opopop−1-11,这样我们就可以将 (l−1,x)(l-1,x)(l1,x) 的结果乘上 opopop 累加到其对应的 ans[id]ans[id]ans[id] 中,表示减去,同理对于 (r,x)(r,x)(r,x)opopop111,表示加上。

#include <bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
#define int long long
#define endl '\n'
#define PII pair<int,int>
#define INF 1e18
const int N = 2e6;template<typename T>// 单点修改和区间查询的树状数组
struct Fenwick {vector <T> tree;int n;Fenwick(int _n) : n(_n), tree(_n + 2){}// 求 1~x 的前缀和T getsum(int x) {T ans = 0;int L = x;while (x) {ans += tree[x];x = x - lowbit(x);}return ans;}// 区间查询T get_range_sum(int l, int r) {return getsum(r) - getsum(l - 1);}// 单点修改void add(int x, T k) {while (x <= n) {tree[x] += k;x += lowbit(x);}}static inline int lowbit(int x) {return x & (-x);}
};struct node {int pos;int x;int id;int op;
};void slove () {int n, m;cin >> n >> m;vector <int> a (n + 1);for (int i = 1; i <= n; i++) cin >> a[i];vector <node> q;for (int i = 1; i <= m; i++) {int l, r, x;cin >> l >> r >> x;q.emplace_back(node{l - 1, x, i, -1});q.emplace_back(node{r, x, i, 1});}sort(q.begin(), q.end(), [](node A, node B) {return A.pos < B.pos;});Fenwick<int> tree(N);vector <int> ans(m + 1, 0);int L = 1, R = 0;while (R < q.size()) {auto now = q[R];while (L <= n && L <= now.pos) {tree.add(a[L], 1);L ++;}ans[now.id] += now.op * tree.get_range_sum(1, now.x);R ++;}for (int i = 1; i <= m; i ++) {cout << ans[i] << endl;}
}signed main () {ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);slove();
}
http://www.dtcms.com/a/316172.html

相关文章:

  • 学习日志28 python
  • AI编程新时代:从氛围编程到上下文编程的深度实践和思考
  • 鸿蒙开发、大数据开发、Java开发与前端开发全面对比解析
  • 【银行测试】银行票据项目业务+票据测试点分析(四)
  • 2025《艾诺提亚失落之歌》逆向工程解包尝试
  • Linux网络编程:TCP初体验
  • VirtualBox安装教程
  • 64位程序调用32位dll方法
  • 【Linux系统编程】线程概念与控制
  • 使用valgrind工具检测server端lib库的内存泄漏
  • FT5X06 触摸芯片
  • 【技术教程】如何将 ONLYOFFICE 文档连接到 Confluence
  • nodejs 编程基础01-NPM包管理
  • Android 之 Kotlin
  • 让 Spark 干体力活:用 Java 快速找出最小值
  • GaussDB 并行创建索引
  • Webpack 5 Module Federation 模块共享最佳实践
  • AI智能体的安全困境:防护机制与伦理平衡的艺术
  • 高精度惯性导航IMU传感器供应商价格
  • Python-机器学习初识
  • C结构体的几种定义形式 + typedef结合使用的好处
  • 数分思维14:用户研究与数据分析
  • WordPress如何实现隐藏文章部分内容?WordPress无法解析[hide]...[/hide]这类短代码怎么办?
  • 【机器学习】算法调参的两种方式:网格搜索(枚举)、随机搜索
  • Android 中几种常用布局的优缺点
  • 2023 年 6 月 GESP Python 二级试卷真题+答案+解析
  • 基于 Lyapunov 能量函数的等势面绘制方法 —— MATLAB 实现与工程应用拓展
  • 永磁同步电机的矢量控制
  • CPP引用
  • 组织架构与软件架构协同演进实践指南