【YBT2023寒假Day6 A】寄蒜挤河(计算几何)(线段树)

寄蒜挤河

题目链接:YBT2023寒假Day6 A

题目大意

有一些二维平面上的点,按顺序加入,每次加入一个点后,问你图上有多少个三元点对使得它们构成的三角形严格包含原点,就是原点不能在点上或边上。

思路

发现直接按着求很难搞,似乎只能做到 n2 之类的。
考虑转化一下,求不合法的方案数。

会发现其实不合法的条件是三个点跨越的极角不超过 180
(以原点在直线上的时候是 180 为最大)

考虑每次插入一个 x 时候不合法方案的增加数。
考虑分别找到 x 顺时针逆时针 180 范围极角差最大的点 y,z
那一个方法就是枚举 yx 里面的一个点 u,然后另两个(这三个其中一个包括 x)在 u 逆时针 180 选。

分类讨论一下,如果 ux,那我们设 fxx 逆时针 180 里面点的个数(不算 x 自己),那就是选一个 x 再选一个,就是 fu
如果 u=x,那就是在旁边再选两个,就是 xz 之间点的个数(算 z 不算 xd(d2)

然后我们考虑维护 fx,其实很简单,每次加入 x 的时候把 yx 极角范围内不包括 x 的点 f 值加一即可。
不过要注意你打标记不一定要加上去,要离散点,、之前已经放进来的点你再加(或者用平衡树也行,因为好像说原本打算出的是强制在线)

代码

#include<map> #include<set> #include<cmath> #include<cstdio> #include<algorithm> #define ll long long using namespace std; const ll N = 4e5 + 100; const double pi = acos(-1.0); const double eps = 1e-11; struct dian { ll x, y, id; double k; }a[N], b[N]; ll n, dy[N]; double bk[N]; ll ans[N]; bool cmp(dian x, dian y) { return x.k < y.k; } bool cmp1(double x, double y) { return y - x > eps; } double Abs(double x) {return x < 0 ? -x : x;} ll Abs(ll x) {return x < 0 ? -x : x;} struct XD_tree { ll f[N << 2], lzy[N << 2]; ll wkn[N << 2]; void up(ll now) { f[now] = f[now << 1] + f[now << 1 | 1]; wkn[now] = wkn[now << 1] + wkn[now << 1 | 1]; } void downa(ll now, ll l, ll r, ll x) { lzy[now] += x; f[now] += x * wkn[now]; } void down(ll now, ll l, ll mid, ll r) { if (lzy[now]) { downa(now << 1, l, mid, lzy[now]); downa(now << 1 | 1, mid + 1, r, lzy[now]); lzy[now] = 0; } } void mark(ll now, ll l, ll r, ll pl, ll x) { if (l == r) { wkn[now] = 1; f[now] = x; return ; } ll mid = (l + r) >> 1; down(now, l, mid, r); if (pl <= mid) mark(now << 1, l, mid, pl, x); else mark(now << 1 | 1, mid + 1, r, pl, x); up(now); } void update(ll now, ll l, ll r, ll L, ll R, ll x) { if (L > R) return ; if (L <= l && r <= R) { downa(now, l, r, x); return ; } ll mid = (l + r) >> 1; down(now, l, mid, r); if (L <= mid) update(now << 1, l, mid, L, R, x); if (mid < R) update(now << 1 | 1, mid + 1, r, L, R, x); up(now); } ll query(ll now, ll l, ll r, ll L, ll R) { if (L > R) return 0ll; if (L <= l && r <= R) return f[now]; ll mid = (l + r) >> 1; down(now, l, mid, r); ll re = 0; if (L <= mid) re += query(now << 1, l, mid, L, R); if (mid < R) re += query(now << 1 | 1, mid + 1, r, L, R); return re; } ll queryn(ll now, ll l, ll r, ll L, ll R) { if (L > R) return 0; if (L <= l && r <= R) return wkn[now]; ll mid = (l + r) >> 1; down(now, l, mid, r); ll re = 0; if (L <= mid) re += queryn(now << 1, l, mid, L, R); if (mid < R) re += queryn(now << 1 | 1, mid + 1, r, L, R); return re; } }T; int main() { freopen("geometry.in", "r", stdin); freopen("geometry.out", "w", stdout); scanf("%lld", &n); for (ll i = 1; i <= n; i++) { scanf("%lld %lld", &a[i].x, &a[i].y); a[i].k = atan2(a[i].y, a[i].x); a[i].id = i; b[i] = a[i]; } sort(b + 1, b + n + 1, cmp); for (ll i = 1; i <= n; i++) bk[i] = b[i].k; for (ll i = 1; i <= n; i++) dy[b[i].id] = i; ll ans = 0; for (ll i = 1; i <= n; i++) { ll now = dy[i]; double k2 = a[i].k - pi; if (k2 <= -pi) k2 += 2 * pi; ll x = lower_bound(bk + 1, bk + n + 1, k2, cmp1) - bk; ll l = x, r = now - 1; if (l == n + 1) l = 1; if (r == 0) r = n; if (now != x) { if (l <= r) ans += T.query(1, 1, n, l, r), T.update(1, 1, n, l, r, 1); else ans += T.query(1, 1, n, l, n) + T.query(1, 1, n, 1, r), T.update(1, 1, n, l, n, 1), T.update(1, 1, n, 1, r, 1); } k2 = a[i].k + pi; if (k2 >= pi) k2 -= 2 * pi; x = upper_bound(bk + 1, bk + n + 1, k2, cmp1) - bk - 1; l = now + 1, r = x; if (l == n + 1) l = 1; if (r == 0) r = n; ll num = 0; if (now != x) { if (l <= r) num = T.queryn(1, 1, n, l, r); else num = T.queryn(1, 1, n, l, n) + T.queryn(1, 1, n, 1, r); } ans += 1ll * num * (num - 1) / 2; T.mark(1, 1, n, now, num); printf("%lld\n", 1ll * i * (i - 1) * (i - 2) / 6 - ans); } return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/YBT2023Day6_A.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2022-02-07 【YBT2022寒假Day2 B】【luogu CF809D】模糊序列 / Hitchhiking in the Baltic States(平衡树优化DP)(fhq-Treap)
2022-02-07 【YBT2022寒假Day2 A】期望旅行(Dij)(期望DP)
点击右上角即可分享
微信分享提示