【无码专区8】三角形二维数点——计数有多少个给定点落在三角形区域内

因为只有std,没有自我实现,所以是无码专区

主要是为了训练思维能力

solution才是dls正解,但是因为只有潦草几句,所以大部分会有我自己基于正解上面的算法实现过程,可能选择的算法跟std中dls的实现不太一样。

std可能也会带有博主自己的注释。


problem

平面上有 nnn 个点,(xi,yi)(x_i,y_i)(xi,yi)

qqq 次询问,每次给定三个点 A(x+d,y),B(x,y),C(x,y+d)A(x+d,y),B(x,y),C(x,y+d)A(x+d,y),B(x,y),C(x,y+d)

求有多少个点 (xi,yi)(x_i,y_i)(xi,yi) 在这个三角形内部或边界上。

10s,128MB,all≤1e610s,128MB,all\le 1e610s,128MB,all1e6


my idea

给定的三角新很有特点:是等腰直角三角形且直角边分别与一条坐标轴平行。

并不是任意的一个三角形。那么这个三角形最难处理的自然就是斜边部分,因为不与坐标轴平行。

如果这是个正方形,就是个很简单的二维差分数点问题。

我曾试图用所有的点减去没有落在指定区域的点,但是发现外围图形仍然会被切割成若干个矩形和一个三角形,还是不会计算三角形。❌

我曾试图计算一个点的位置会被多少个三角形覆盖,对这些三角形贡献 111。但是查询的三角形压根不能找到一种范围限制能够说明:横纵坐标简单的加减为某个范围时属于这个三角形。❌

这两种思路都卡在了三角形重叠部分,更具体而言是没有找到要贡献的点坐标的特征性,显然这应该是正解的思路,这导致我们只能尝试不是正解的想法看能否优化跑过。

既然题目给的是平行坐标轴的直角三角形,那么这个直角边一定是切入点。

三角形不好做,但是四边形好做。

将三角形划分成一个四边形,和两个三角形。

如图:一个三角形存在很多种切割方式。

在这里插入图片描述

四边形是很容易计算的,三角形就递归地切割。所以时间复杂度是跟这个三角形切割挂钩的。

出于平衡左右时间的思想,我们肯定会选取“正半分”,使得两个三角形“完全一样”。

【但是如果只计算整点,“正半分”可能是分数,所以是尽可能地“正半分”,让两边地效率尽可能平衡。】

在这里插入图片描述

这种递归思想就是——分治。

没错,我们可以采取分而治之的做法,递归求解计算。

最底层的出口就是直角边某一条长度为 111 的三角形,统计另一条边的贡献即可。

这样,划分最多 logloglog 层。

四边形的计算由于 N×MN\times MN×M 根本开不下,无法预处理然后 O(1)O(1)O(1) 差分求解。

只能采取数据结构计算。

具体而言:

nnn 个点按 xxx 第一关键字,yyy 第二关键字排序。

需要在划分的一个区间内查询一个区间的问题。又是它!——主席树。

yyy 建立线段树,第 iii 个版本维护的是前 iii 个点的主席数信息,权值线段树。

线段树上节点维护 y∈[l,r]y\in[l,r]y[l,r] 的点有多少个。

i→i+1i\rightarrow i+1ii+1,单点更新 yiy_iyi

查询 (x1,y1,x2,y2)(x1,y1,x2,y2)(x1,y1,x2,y2)。找到 x1<xlx1<x_lx1<xl 的最小 lll,以及 xr<x2xr<x2xr<x2 的最大 rrr。二分查找。

然后就询问 l∼rl\sim rlr 版本中 [y1,y2][y1,y2][y1,y2] 内点的个数。

这样来看数据结构自带两个 logloglog,外层还有一个。时间复杂度是 O(nlog3n)O(nlog^3n)O(nlog3n) 的。

只能堪堪通过 70%70\%70% 的数据点 2×1052\times 10^52×105

【计算出来大概是 8e88e88e8 的,10s10s10s1e91e91e9,常数小写得好看应该是能跑过的。】

考虑优化,优化掉二分查找的 logloglog

最开始排序的 logloglog 省不了。

对于 iii,直接二分找 l,rl,rl,r 记录下来 Li,RiL_i,R_iLi,Ri

这样是将里面嵌套的 logloglog 放在了外面。

O(nlog⁡3n)→O(nlog⁡2n+nlog⁡n)O(n\log^3n)\rightarrow O(n\log^2n+n\log n)O(nlog3n)O(nlog2n+nlogn)

就是两个 logloglog 的了。

算出来 4e84e84e8,相对与 1e91e91e9 而言应该是绰绰有余的,常数大点应该没关系。

trick:图上一条线段分裂,但实际上计算的时候并不重叠。

中间界可以划给三角形部分,也可以是矩形部分。

但具体实现会发现,将中间界划分给三角形会比较好算,因为是封闭的。

不好说明,给图直观感受。

在这里插入图片描述

但是也不是说不能写,应该也是能实现的。


solution

直接查询,就是三维数点问题。CDQCDQCDQ 分治做 O(nlog⁡2n)O(n\log^2n)O(nlog2n)

又来了,一句话一页阐释。

为什么是三维数点??怎么数??


扩展:如何用三角形的三个坐标表示三角形中任意一点的坐标。

假设三角形三点分别为 A(x1,y1),B(x2,y2),C(x3,y3)A(x1,y1),B(x2,y2),C(x3,y3)A(x1,y1),B(x2,y2),C(x3,y3),现要表示内部点 O(x,y)O(x,y)O(x,y)

设射线 AOAOAOBCBCBC 与点 DDDAO⃗=mAD⃗,BD⃗=nBC⃗\vec{AO}=m\vec{AD},\vec{BD}=n\vec{BC}AO=mAD,BD=nBC

AO⃗=mAD⃗=m(AB⃗+BD⃗)=mAB⃗+mnBC⃗\vec{AO}=m\vec{AD}=m(\vec{AB}+\vec{BD})=m\vec{AB}+mn\vec{BC}AO=mAD=m(AB+BD)=mAB+mnBC

即:
(x−x1,y−y1)=m(x2−x1,y2−y1)+mn(x3−x2,y3−y2)(x-x1,y-y1)=m(x2-x1,y2-y1)+mn(x3-x2,y3-y2) (xx1,yy1)=m(x2x1,y2y1)+mn(x3x2,y3y2)

=(m(x2−x1)+mn(x3−x2),m(y2−y1)+mn(y3−y2))=(m(x2-x1)+mn(x3-x2),m(y2-y1)+mn(y3-y2)) =(m(x2x1)+mn(x3x2),m(y2y1)+mn(y3y2))

⇒{x−x1=m(x2−x1)+mn(x3−x2)⇒x=x1(1−m)+x2(m−mn)+x3mny−y1=m(y2−y1)+mn(y3−y2)⇒y=y1(1−m)+y2(m−mn)+y3mn\Rightarrow\begin{cases}x-x1=m(x2-x1)+mn(x3-x2)\Rightarrow x=x1(1-m)+x2(m-mn)+x3mn\\y-y1=m(y2-y1)+mn(y3-y2)\Rightarrow y=y1(1-m)+y2(m-mn)+y3mn\\\end{cases} {xx1=m(x2x1)+mn(x3x2)x=x1(1m)+x2(mmn)+x3mnyy1=m(y2y1)+mn(y3y2)y=y1(1m)+y2(mmn)+y3mn

换元表示 a=1−m,b=m−mna=1-m,b=m-mna=1m,b=mmn ,则
{x=a⋅x1+b⋅x2+(1−a−b)x3y=a⋅y1+b⋅y2+(1−a−b)y3\begin{cases}x=a·x1+b·x2+(1-a-b)x3\\y=a·y1+b·y2+(1-a-b)y3\\\end{cases} {x=ax1+bx2+(1ab)x3y=ay1+by2+(1ab)y3

dbq,我确实没看懂这个三维数点怎么做。

观察性质,三角形区域 (x′,y′)−(x′+d,y′)−(x′,y′+d)(x',y')-(x'+d,y')-(x',y'+d)(x,y)(x+d,y)(x,y+d)
相当于总区域减去 x<x′,y<y′,x+y>x′+y′+dx<x',y<y',x+y>x'+y'+dx<x,y<y,x+y>x+y+d 三个半平面。
然后补上三个被减了两次的区域。
x<x′∧y<y′,x<x′∧x+y>x′+y′+d′,y<y′∧x+y>x′+y′+dx<x'\wedge y<y',x<x'\wedge x+y>x'+y'+d',y<y'\wedge x+y>x'+y'+dx<xy<y,x<xx+y>x+y+d,y<yx+y>x+y+d

这三个部分都是二维数点,直接做,时间复杂度 O(nlog⁡n)O(n\log n)O(nlogn)

其实看题解的时候我并不懂,但是一看代码就懂了!!

原来是我不会等腰直角三角形的二维数点!!其实很简单。


code

在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
#define FOR(a,b,c) for (int a=b,_c=c;a<=_c;a++)
#define FORD(a,b,c) for (int a=b;a>=c;a--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; ++i)
#define REPD(i,a) for(int i=(a)-1; i>=0; --i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007using namespace std;typedef long long ll;
typedef pair<int, int> pii;const int maxn = 1000007;
const int maxv = 1000007;int n, q, BIT[maxn], ans[maxn];
struct node {int x, y, d, id;
} a[maxn * 2];bool cmp1(const node &a, const node &b) {return a.y < b.y || (a.y == b.y && a.id > b.id);
}bool cmp2(const node &a, const node &b) {int v1 = a.x + a.y + a.d;int v2 = b.x + b.y + b.d;return v1 < v2 || (v1 == v2 && a.id < b.id);
}void update(int p) {for (int i = p; i <= maxv; i += i & (-i))BIT[i]++;
}int get(int p) {int ans = 0;p = min(p, maxv);for (int i = p; i; i -= i & (-i))ans += BIT[i];return ans;
}int main() {freopen("triangular.in", "r", stdin);freopen("triangular.out", "w", stdout);scanf("%d%d", &n, &q);FOR(i, 1, n) {scanf("%d%d", &a[i].x, &a[i].y);a[i].id = 0;}FOR(i, 1, q) {scanf("%d%d%d", &a[i + n].x, &a[i + n].y, &a[i + n].d);a[i + n].id = i;}sort(a + 1, a + n + q + 1, cmp1);FOR(i, 1, n + q)if (a[i].id)ans[a[i].id] -= get(a[i].x + a[i].d) - get(a[i].x - 1);elseupdate(a[i].x);sort(a + 1, a + n + q + 1, cmp2);reset(BIT, 0);FOR(i, 1, n + q)if (a[i].id)ans[a[i].id] += get(a[i].x + a[i].d) - get(a[i].x - 1);elseupdate(a[i].x);FOR(i, 1, q) printf("%d\n", ans[i]);return 0;
}

总结

这道题大概断断续续想了两天(每天 40min40min40min 左右)吧,当我突然意识到分拆递归处理的时候,后面的进展就比较快了。

其实std的做法是很有局限性的,必须充分利用等腰直角,直角边平行于坐标轴三个条件,但也是挺妙的。

但是我的想法是可以扔掉等腰这个条件的,只需要直角三角形,直角边平行于坐标轴就可以了,但是多了个 logloglog

当然这也是我的想法,我也不知道是否正确,欢迎友好讨论以及分享不同思路。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316763.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P3426 [POI2005]SZA-Template(kmp、dp)

解析 做出来了就是胜利&#xff01; 个人感觉虽然我这个nxt树的码量会大一点&#xff0c;但是思路其实比较自然。&#xff08;看题解区也有&#xff09; 也是一个相当可取的做法。 现在来讲讲巧妙的dp做法。 考虑直接嗯设&#xff1a;fif_ifi​ 表示覆盖 [1,i][1,i ][1,i] 的…

为什么我的会话状态在ASP.NET Core中不工作了?

原文&#xff1a;Why isnt my session state working in ASP.NET Core? Session state, GDPR, and non-essential cookies作者&#xff1a;Andrew Lock译文&#xff1a;https://www.cnblogs.com/lwqlun/p/10526380.html译者&#xff1a;Lamond Lu在本篇博客中&#xff0c;我将…

Jury Compromise POJ - 1015

Jury Compromise POJ - 1015 题意&#xff1a; 在遥远的国家佛罗布尼亚&#xff0c;嫌犯是否有罪&#xff0c;须由陪审团决定。陪审团是由法官从公众中挑选的。先随机挑选n个人作为陪审团的候选人&#xff0c;然后再从这n个人中选m人组成陪审团。选m人的办法是&#xff1a; 控…

叁仟柒佰万(mex+线段树+dp+前缀和优化+双指针+桶)

叁仟柒佰万problemsolutioncode(50’)code(90’)code(100’)problem 多组数据。 给定一个序列 aaa&#xff0c;你可以将它划分成任意多段&#xff0c;满足每一个段的 mex 相同。 求方案数&#xff0c;对 109710^971097 取模。 T≤10,n≤3e5T\le 10,n\le 3e5T≤10,n≤3e5。 …

模板:吉司机线段树

所谓吉司机线段树&#xff0c;就是吉司机种的线段树 &#xff08;逃&#xff09; 解析 之前也看过一些相关内容的博客&#xff0c;但是因标记乱七八糟&#xff0c;感觉过于高深而放弃了… 直到看到洛谷这篇博客&#xff0c;完全颠覆了我的认知。&#xff08;怎么感觉语气像营…

现身说法:实际业务出发分析百亿数据量下的多表查询优化

今天给大家带来的讨论主题是通过实战经验来对百亿数据量下的多表数据查询进行优化&#xff0c;俗话说的好&#xff0c;一切脱离业务的架构都是耍流氓&#xff0c;接下来我就整理一下今天早上微信群里石头哥给大家分享的百亿数据量多表查询架构以及优化思路。由于本文内容整理自…

Help Jimmy POJ - 1661

Help Jimmy POJ - 1661 题意&#xff1a; 场景中包括多个长度和高度各不相同的平台。地面是最低的平台&#xff0c;高度为零&#xff0c;长度无限。 Jimmy老鼠在时刻0从高于所有平台的某处开始下落&#xff0c;它的下落速度始终为1米/秒。当Jimmy落到某个平台上时&#xff0c…

[HDU 6643] Ridiculous Netizens(点分治+根号分治+dp)

HDU 6643 Ridiculous Netizens problem hdu6643 题目大意&#xff1a;给定一棵无根树&#xff0c;以及每个点的点权 wiw_iwi​。 定义一个连通块的价值为连通块内点的点权之积。 求有多少个连通块价值 ≤m\le m≤m。 n≤2e3,m≤1e6n\le 2e3,m\le 1e6n≤2e3,m≤1e6。 solu…

SP422 TRANSP2 - Transposing is Even More Fun(Burnside引理,莫比乌斯反演)

解析 很巧妙的题。 关键是要利用好边长为2的整数次幂的性质。 对下标从1开始党极不友好。 首先显然答案就是 2ab2^{ab}2ab -环。 让下标均从0开始。 对于一个点 (i,j)(i,j)(i,j)&#xff0c;它原来的内存地址为 i∗2aji*2^aji∗2aj&#xff0c;转置后的地址为 j∗2bij*2^bij∗…

Fireworks(2020 ICPC南京)

Fireworks 题意&#xff1a; 你每做一个烟花要n分钟&#xff0c;释放已做好的所有烟花需要m分钟&#xff0c;每只烟花成功释放的概率为p。问你在采取最优策略的前提下&#xff0c;直到成功释放第一个烟花时最小的期望时间花费。 题解&#xff1a; 最佳策略是&#xff1a;每…

ASP.NET Core 沉思录 - ServiceProvider 的二度出生

ASP.NET Core 终于将几乎所有的对象创建工作都和依赖注入框架集成了起来。并对大部分的日常工作进行了抽象。使得整个框架扩展更加方便。各个部分的集成也更加容易。今天我们要思考的部分仍然是从一段每一个工程中都大同小异的代码开始的。IWebHostBuilder CreateWebHostBuilde…

[SPOJ - FTOUR2] Free tour II(点分治 + 背包dp + 启发式合并)

SPOJ - FTOUR2 Free tour II problem 给定一棵树&#xff0c;以及 mmm 个拥挤城市编号&#xff0c;选择一条最多包含 kkk 个拥挤城市的简单路径。 每条边有一个有趣度 www&#xff0c;可正可负。简单路径的价值定义为包含边的有趣度之和。 求最大价值。n≤2e5,∣w∣≤1e4n\…

PKUSC2022 游记

前言 1001822698014095235。 题的难度感觉比去年难不少&#xff0c;主要的体现在于两天的T1都没有之前那么可做了&#xff0c;在信息差的影响下几乎成了两场崩盘场。 由于比赛时间变短的原因&#xff0c;模拟反而比历年简单不少。 遗憾&#xff1a; d1t3的网络流莫名其妙无法…

Acwing 216. Rainbow的信号

Acwing 216. Rainbow的信号 题意&#xff1a; 给你n个数&#xff0c;在这n个数中&#xff0c;等概率地选取两个数l&#xff0c;r&#xff0c;如果l>r,则交换l,r 把信号中的第 l 个数到第 r 个数取出来&#xff0c;构成一个数列 P。 A 部分对话的密码是数列 P 的 xor 和的…

微软开源故事 | 开启 .NET 开源革命

如今&#xff0c;在微软构建开源软件是很正常的一件事——但早在2007年&#xff0c;我开始在微软工作时&#xff0c;情况并非如此。我们花了几年的时间才找到正确的方法&#xff0c;顺利开启了微软的开源之路。但是&#xff0c;如今我们已取得胜利&#xff0c;可以面带微笑地回…

【无码专区9】序列统计(带权并查集 + 前缀和建边 + dp)

因为只有std&#xff0c;没有自我实现&#xff0c;所以是无码专区 主要是为了训练思维能力 solution才是dls正解&#xff0c;但是因为只有潦草几句&#xff0c;所以大部分会有我自己基于正解上面的算法实现过程&#xff0c;可能选择的算法跟std中dls的实现不太一样。 std可能…

Acwing 217. 绿豆蛙的归宿

Acwing 217. 绿豆蛙的归宿 题意&#xff1a; 给出一个有向无环的连通图&#xff0c;起点为 1&#xff0c;终点为 N&#xff0c;每条边都有一个长度。 数据保证从起点出发能够到达图中所有的点&#xff0c;图中所有的点也都能够到达终点。 绿豆蛙从起点出发&#xff0c;走向…

LNOI2022:游记

前言 The world is cruel. 真的为身边的一些人感到可惜… Day -1 PKUSC刚刚考完&#xff0c;然后就要省选了&#xff1f; 板子实在是看的够够的了。 然而还是不想深度做题&#xff0c;看了看APIO的practise&#xff0c;T1写完发现偶数还得特别做&#xff0c;就感觉很麻烦&…

合肥.NET技术社区首次线下聚会全程回顾【多图】

2019年3月16日对于合肥.NET来说是一个特别的日子&#xff0c;因为这是合肥.NET技术社区首次非正式线下聚会&#xff01;这次聚会受场地限制&#xff08;毕竟是聚餐的形式&#xff09;&#xff0c;即使换成了小椅子后&#xff0c;最多也只能容纳24个人&#xff0c;所以还有一些小…

【无码专区10】第K大查询(双向链表 /主席树+st表)

已自我实现&#xff0c;但还是归入无码专区序列。哈哈哈哈哈 对于my idea部分&#xff0c;我的每一个想法都实现了&#xff0c;可供参考。 problem 给定一个 1∼n1\sim n1∼n 的排列和 kkk&#xff0c;求所有 r−l1≥kr-l1\ge kr−l1≥k 的区间 [l,r][l,r][l,r] 中的第 kkk 大…