二维数点问题

1|0二维数点问题

1|0整体思路

将所有点按x值从小到大排序,那么查询满足特定条件的点的时候,可以转化为只对y值查询,由此,只需要遍历横坐标,并在遍历过程中用树状数组等数据结构维护对y的操作即可。

1|1P2163 [SHOI2007] 园丁的烦恼

题目链接:园丁的烦恼

1|0题意

给n个点,m次询问,每次询问给出一个矩形,对于每次询问回答每个矩形里包含多少个点。不要求在线, 0n5×105,1m5×105,0x,y,a,b,c,d107,ac,bd

1|0思路

由于是离线的,可以把每个矩形看成从(0,0)开始的四个矩形部分内点的数量加减得到的,即:

Ntotal=Nx2,y2Nx11,y2Nx2,y11+Nx11,y11

这样我们可以把矩形对应的四个点全部放到一个数组里,对其按从小到大排序即可(重载运算符,按横坐标从小到大,纵坐标从下到大排序)。
依次遍历排完序后每个矩阵的点,依次向树状数组中“小于”当前点的点的值加一,查询所有“小于”当前点的y值的点的个数,累加(或累减)到对应的第id次查询的答案中即可。
注意:由于树状数组的输入和查询是从1到x,而本题中的x和y是从0开始,因此需要把坐标都先加一。
由于y值只到1e7,所以可不进行离散化(该题测试数据比较水,测试集的y值最大似乎还不到5e5)

1|0代码

#include <bits/stdc++.h> using namespace std; const int maxn = 5e5 + 5, maxnn = 1e7 + 3; struct poi { int x, y; bool operator<(const poi b) const { return x < b.x || (x == b.x && y < b.y); } bool operator==(const poi b) const { return x == b.x && y == b.y; } } a[maxn]; struct matrix { poi x; int k, id; bool operator<(const matrix b) const { return x < b.x; } } q[4 * maxn]; int lowbit(int x) { return x & -x; } int y[maxnn], n, m, ans[maxn]; void add(int x, int d) { while (x <= n) { y[x] += d; x += lowbit(x); } } int query(int x) { int sum = 0; while (x > 0) { sum += y[x]; x -= lowbit(x); } return sum; } void sol() { cin >> n >> m; for (int i = 1; i <= n; ++i) cin >> a[i].x >> a[i].y; for (int i = 1; i <= n; ++i) a[i].x++, a[i].y++; sort(a + 1, a + n + 1); for (int i = 1; i <= m; ++i) { int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; q[4 * i - 3] = matrix{x1, y1, 1, i}; q[4 * i - 2] = matrix{x2 + 1, y2 + 1, 1, i}; q[4 * i - 1] = matrix{x1, y2 + 1, -1, i}; q[4 * i] = matrix{x2 + 1, y1, -1, i}; } m *= 4; sort(q + 1, q + m + 1); int idx = 1; for (int i = 1; i <= m; ++i) { while (idx <= n && (a[idx] < q[i].x || a[idx] == q[i].x)) { add(a[idx].y, 1); idx++; } ans[q[i].id] += q[i].k * query(q[i].x.y); } for (int i = 1; i <= m / 4; ++i) cout << ans[i] << endl; } int main() { sol(); return 0; }

1|2P3755 [CQOI2017] 老C的任务

原文链接:老C的任务https://www.luogu.com.cn/problem/P3755

1|0题意

给n个点,每个点都有一个权值,有m个询问,每个询问一个矩形,问矩形内点的权值和为多少。不要求在线,1n,m1e5,231<xi,yi,pi,x1j,y1j,x2j,y2j<231,x1jx2j,y1jy2j

1|0思路

跟上题的差别在于,这个题x,y坐标值范围更广,需要离散化,并且权值范围覆盖整个int取值范围,需要适当地用long long避免溢出。
这个题测试数据也很坑,n,m的范围写的是1e5,但是实测发现maxn需要改到3e5才对(也可能我写的有错误我没看到,如果有发现,可以评论,感谢指正)。而很明显容易出问题的数据范围方面,又没有测试点卡着,导致有的题解随便出个卡边界的数据就寄了,但是能过该题。

1|0代码

#include <bits/stdc++.h> #define LL long long using namespace std; const int maxn = 3e5 + 5; struct poi { LL x, y; bool operator<(const poi b) const { return x < b.x || (x == b.x && y < b.y); } bool operator==(const poi b) const { return x == b.x && y == b.y; } }; pair<poi, int> a[maxn]; struct matrix { poi x; int k, id; bool operator<(const matrix b) const { return x < b.x; } } q[4 * maxn]; LL y[5 * maxn], ans[maxn]; int n, m; vector<LL> all_y; int lowbit(int x) { return x & -x; } void add(int x, int d) { while (x <= n + 4 * m) { y[x] += d; x += lowbit(x); } } LL query(int x) { LL sum = 0; while (x > 0) { sum += y[x]; x -= lowbit(x); } return sum; } void sol() { cin >> n >> m; for (int i = 1; i <= n; ++i) cin >> a[i].first.x >> a[i].first.y >> a[i].second, all_y.push_back(a[i].first.y); sort(a + 1, a + n + 1); for (int i = 1; i <= m; ++i) { LL x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; q[4 * i - 3] = matrix{x1 - 1, y1 - 1, 1, i}; q[4 * i - 2] = matrix{x2, y2, 1, i}; q[4 * i - 1] = matrix{x1 - 1, y2, -1, i}; q[4 * i] = matrix{x2, y1 - 1, -1, i}; all_y.push_back(y2); all_y.push_back(y1 - 1); } sort(all_y.begin(), all_y.end()); m *= 4; sort(q + 1, q + m + 1); int idx = 1; for (int i = 1; i <= m; ++i) { while (idx <= n && (a[idx].first < q[i].x || a[idx].first == q[i].x)) { int y_idx = lower_bound(all_y.begin(), all_y.end(), a[idx].first.y) - all_y.begin() + 1; add(y_idx, a[idx].second); idx++; } int y_idx = lower_bound(all_y.begin(), all_y.end(), q[i].x.y) - all_y.begin() + 1; ans[q[i].id] += q[i].k * query(y_idx); } for (int i = 1; i <= m / 4; ++i) cout << ans[i] << endl; } int main() { sol(); return 0; }

__EOF__

本文作者FlyingLight
本文链接https://www.cnblogs.com/FlyingLight/p/17528313.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FlyingLight  阅读(390)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示