当前位置: 首页 > 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.lryc.cn/news/610962.html

相关文章:

  • Dell电脑Windows系统更新后声卡驱动无法识别插线耳机问题
  • 第13届蓝桥杯Scratch_选拔赛_初级组_真题2022年1月22日
  • leetcode-python-删除链表的倒数第 N 个结点
  • Leetcode 13 java
  • Linux网络编程:TCP初体验
  • 从递归到动态规划-解码方法Ⅱ
  • 【IDEA】IntelliJ IDEA 中文官方文档全面介绍与总结
  • 以Linux为例补充内存管理基础知识
  • 2025年服务器僵尸攻防战:从AI勒索到量子免疫,构建下一代“数字抗体”
  • Linux 常用命令大全
  • 基于vscode连接服务器实现远程开发
  • vi编辑器makefile的使用以及双向链表
  • 【C++详解】⼆叉搜索树原理剖析与模拟实现、key和key/value,内含优雅的赋值运算符重载写法
  • PHP实战代码解析与应用分享:用户管理、日志,配置管理与文件操作全解析
  • PostgreSQL——插入、更新与删除数据
  • [数组]977.有序数组的平方;209.长度最小的子数组
  • 初始化列表,变量存储区域和友元变量
  • Linux系统目录分析
  • 复杂环境跌倒识别准确率↑31%!陌讯多模态算法在智慧养老的落地实践
  • 2. JS 有哪些数据类型
  • 基于Redis实现短信登录
  • 【CTF】命令注入绕过技术专题:变量比较与逻辑运算
  • Redis Stream:高性能消息队列核心原理揭秘
  • 【OSCP】- eLection 靶机学习
  • 基于ARM+FPGA光栅数据采集卡设计
  • Electron-updater + Electron-builder + IIS + NSIS + Blockmap 完整增量更新方案
  • GPT-1、GPT-2、GPT-3 的区别和联系
  • 7、Redis队列Stream和单线程及多线程模型
  • 人工智能领域、图欧科技、IMYAI智能助手2025年4月更新月报
  • 【RK3576】【Android14】Uboot下fastboot命令支持