From 6f2236af752c4c0a9ee2ad6d7f548a55331b5bff Mon Sep 17 00:00:00 2001 From: Nachia Vivias Date: Wed, 27 Dec 2023 22:05:59 +0900 Subject: [PATCH 1/4] Add count_points_in_triangle --- geo/count_points_in_triangle/checker.cpp | 62 ++++++++++++ geo/count_points_in_triangle/gen/dence.cpp | 35 +++++++ .../gen/example_00.in | 17 ++++ .../gen/max_random.cpp | 35 +++++++ .../gen/middle_random.cpp | 35 +++++++ geo/count_points_in_triangle/hash.json | 22 +++++ geo/count_points_in_triangle/info.toml | 27 +++++ geo/count_points_in_triangle/sol/correct.cpp | 98 +++++++++++++++++++ geo/count_points_in_triangle/sol/naive.cpp | 58 +++++++++++ geo/count_points_in_triangle/task.md | 55 +++++++++++ geo/count_points_in_triangle/verifier.cpp | 35 +++++++ 11 files changed, 479 insertions(+) create mode 100644 geo/count_points_in_triangle/checker.cpp create mode 100644 geo/count_points_in_triangle/gen/dence.cpp create mode 100644 geo/count_points_in_triangle/gen/example_00.in create mode 100644 geo/count_points_in_triangle/gen/max_random.cpp create mode 100644 geo/count_points_in_triangle/gen/middle_random.cpp create mode 100644 geo/count_points_in_triangle/hash.json create mode 100644 geo/count_points_in_triangle/info.toml create mode 100644 geo/count_points_in_triangle/sol/correct.cpp create mode 100644 geo/count_points_in_triangle/sol/naive.cpp create mode 100644 geo/count_points_in_triangle/task.md create mode 100644 geo/count_points_in_triangle/verifier.cpp diff --git a/geo/count_points_in_triangle/checker.cpp b/geo/count_points_in_triangle/checker.cpp new file mode 100644 index 000000000..6a66d5330 --- /dev/null +++ b/geo/count_points_in_triangle/checker.cpp @@ -0,0 +1,62 @@ +// https://github.com/MikeMirzayanov/testlib/blob/master/checkers/wcmp.cpp + +// The MIT License (MIT) + +// Copyright (c) 2015 Mike Mirzayanov + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include "testlib.h" + +using namespace std; + +int main(int argc, char * argv[]) +{ + setName("compare sequences of tokens"); + registerTestlibCmd(argc, argv); + + int n = 0; + string j, p; + + while (!ans.seekEof() && !ouf.seekEof()) + { + n++; + + ans.readWordTo(j); + ouf.readWordTo(p); + + if (j != p) + quitf(_wa, "%d%s words differ - expected: '%s', found: '%s'", n, englishEnding(n).c_str(), compress(j).c_str(), compress(p).c_str()); + } + + if (ans.seekEof() && ouf.seekEof()) + { + if (n == 1) + quitf(_ok, "\"%s\"", compress(j).c_str()); + else + quitf(_ok, "%d tokens", n); + } + else + { + if (ans.seekEof()) + quitf(_wa, "Participant output contains extra tokens"); + else + quitf(_wa, "Unexpected EOF in the participants output"); + } +} diff --git a/geo/count_points_in_triangle/gen/dence.cpp b/geo/count_points_in_triangle/gen/dence.cpp new file mode 100644 index 000000000..841ad459f --- /dev/null +++ b/geo/count_points_in_triangle/gen/dence.cpp @@ -0,0 +1,35 @@ +#include +#include + +#include "../params.h" +#include "random.h" +using namespace std; + +int main(int, char* argv[]) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = N_MAX; + int m = M_MAX; + int q = Q_MAX; + printf("%d\n", n); + for (int i=0; i +#include + +#include "../params.h" +#include "random.h" +using namespace std; + +int main(int, char* argv[]) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = N_MAX; + int m = M_MAX; + int q = Q_MAX; + printf("%d\n", n); + for (int i=0; i +#include + +#include "../params.h" +#include "random.h" +using namespace std; + +int main(int, char* argv[]) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = N_MAX; + int m = M_MAX; + int q = min(Q_MAX, 4000'0000 / m); + printf("%d\n", n); + for (int i=0; i +#include +#include +#include + +template +struct VecI2 { + Int x, y; + VecI2() : x(0), y(0) {} + VecI2(Int _x, Int _y) : x(_x), y(_y) {} + VecI2 operator+(VecI2 r) const { return VecI2(x+r.x, y+r.y); } + VecI2 operator-(VecI2 r) const { return VecI2(x-r.x, y-r.y); } + VecI2 operator-() const { return VecI2(-x, -y); } + Int2 operator*(VecI2 r) const { return Int2(x) * Int2(r.x) + Int2(y) * Int2(r.y); } + Int2 operator^(VecI2 r) const { return Int2(x) * Int2(r.y) - Int2(y) * Int2(r.x); } + static bool compareYX(VecI2 a, VecI2 b){ return a.y < b.y || (!(b.y < a.y) && a.x < b.x); } + static bool compareXY(VecI2 a, VecI2 b){ return a.x < b.x || (!(b.x < a.x) && a.y < b.y); } +}; + + +using i64 = long long; +using namespace std; +using Vec = VecI2; +#define rep(i,n) for(int i=0; i<(int)(n); i++) + +int main(){ + int N; scanf("%d", &N); + vector A(N); + rep(i,N) scanf("%lld%lld", &A[i].x, &A[i].y); + int M; scanf("%d", &M); + vector B(M); + rep(i,M) scanf("%lld%lld", &B[i].x, &B[i].y); + + auto pointL = vector(N); // bx < Ax + auto pointM = vector(N); // bx = Ax + rep(i,N) rep(j,M) if(A[i].y == B[j].y){ + if(B[j].x < A[i].x) pointL[i]++; + if(B[j].x == A[i].x) pointM[i]++; + } + + auto edgeL = vector>(N, vector(N)); // bx < lerp(Ax, Bx) + auto edgeM = vector>(N, vector(N)); // bx = lerp(Ax, Bx) + rep(a,N) rep(b,N) if(A[a].y < A[b].y){ + rep(i,M) if(A[a].y < B[i].y && B[i].y < A[b].y){ + auto det = (A[a] - A[b]) ^ (B[i] - A[b]); + if(det < 0) edgeL[a][b]++; + if(det == 0) edgeM[a][b]++; + } + } + + int Q; scanf("%d", &Q); + rep(qi, Q){ + int a,b,c; scanf("%d%d%d", &a, &b, &c); + if(Vec::compareYX(A[b], A[a])) swap(a, b); + if(Vec::compareYX(A[c], A[b])) swap(b, c); + if(Vec::compareYX(A[b], A[a])) swap(a, b); + // c ^y + // b | + // a +---> x + + // c + // nega | + // v posi + // a + auto det = (A[a] - A[c]) ^ (A[b] - A[c]); + int ans = 0; + if(det != 0){ + if(A[a].y == A[b].y){ // A[a].x < A[b].x + // c + // a b + ans = edgeL[b][c] - (edgeL[a][c] + edgeM[a][c]); + } else if(A[b].y == A[c].y){ // A[b].x < A[c].x + // b c + // a + ans = edgeL[a][c] - (edgeL[a][b] + edgeM[a][b]); + } else if(det < 0){ + // c + // b + // a + ans += edgeL[a][c]; + ans -= edgeL[b][c] + edgeM[b][c]; + ans -= edgeL[a][b] + edgeM[a][b]; + ans -= pointL[b] + pointM[b]; + } else { + // c + // b + // a + ans += edgeL[a][b]; + ans += edgeL[b][c]; + ans += pointL[b]; + ans -= edgeL[a][c] + edgeM[a][c]; + } + } + printf("%d\n", ans); + } + return 0; +} diff --git a/geo/count_points_in_triangle/sol/naive.cpp b/geo/count_points_in_triangle/sol/naive.cpp new file mode 100644 index 000000000..ef3a5d4d5 --- /dev/null +++ b/geo/count_points_in_triangle/sol/naive.cpp @@ -0,0 +1,58 @@ + +#include +#include +#include +using i64 = long long; +#define rep(i,n) for(int i=0; i<(int)(n); i++) + +int main(){ + using namespace std; + int N; scanf("%d", &N); + vector Ax(N), Ay(N); + rep(i,N) scanf("%lld%lld", &Ax[i], &Ay[i]); + int M; scanf("%d", &M); + vector Bx(M), By(M); + rep(i,M) scanf("%lld%lld", &Bx[i], &By[i]); + + int Q; scanf("%d", &Q); + rep(qi, Q){ + int a,b,c; scanf("%d%d%d", &a, &b, &c); + i64 xab = Ax[b] - Ax[a]; + i64 yab = Ay[b] - Ay[a]; + i64 xac = Ax[c] - Ax[a]; + i64 yac = Ay[c] - Ay[a]; + if(xab * yac - yab * xac == 0){ + printf("0\n"); + continue; + } + if(xab * yac - yab * xac < 0){ + swap(xab, xac); + swap(yab, yac); + swap(b, c); + } + // c + // + // a -----> b + int ans = 0; + rep(m,M){ + bool ok = true; + rep(t,3){ + i64 xV = Ax[b] - Ax[a]; + i64 yV = Ay[b] - Ay[a]; + i64 xW = Bx[m] - Ax[a]; + i64 yW = By[m] - Ay[a]; + if(xV * yW - yV * xW <= 0){ + // a ---V--> b + // -_ + // W-_ + // ->x (border ng) + ok = false; + } + swap(a,b); swap(b,c); + } + if(ok) ans++; + } + printf("%d\n", ans); + } + return 0; +} diff --git a/geo/count_points_in_triangle/task.md b/geo/count_points_in_triangle/task.md new file mode 100644 index 000000000..774b6ed6f --- /dev/null +++ b/geo/count_points_in_triangle/task.md @@ -0,0 +1,55 @@ +## @{keyword.statement} + +@{lang.en} +Given 2D-points $A _ k=(x _ k, y _ k)$ $(k=0,1,\ldots ,N-1)$ and 2D-points $B _ k=(p _ k, q _ k)$ $(k=0,1,\ldots ,M-1)$ . Process the following $Q$ queries in order. + +* Given $a$ , $b$ , $c$ . Please output the number of points in $B _ 0,B _ 1,\ldots ,B _ {M-1}$ included in the convex hull of $3$ points $A _ a,A _ b,A _ c$ (**exclude border**) . + +@{lang.ja} +2D の点 $A _ k=(x _ k, y _ k)$ $(k=0,1,\ldots ,N-1)$ と 2D の点 $B _ k=(p _ k, q _ k)$ $(k=0,1,\ldots ,M-1)$ が与えられます。以下の $Q$ 個のクエリに順に答えてください。 + +* $a$ , $b$ , $c$ が与えられます。 $B _ 0,B _ 1,\ldots ,B _ {M-1}$ のうち、 $3$ 点 $A _ a,A _ b,A _ c$ の凸包の内部 (**境界を除く**) にあるものの個数を出力してください。 +@{lang.end} + +## @{keyword.constraints} + +@{lang.en} +- $1 \leq N \leq @{param.N_MAX}$ +- $1 \leq M \leq @{param.M_MAX}$ +- $|x _ i|, |y _ i| \leq @{param.X_AND_Y_ABS_MAX}$ +- $|p _ i|, |q _ i| \leq @{param.X_AND_Y_ABS_MAX}$ +- $1 \leq Q \leq @{param.Q_MAX}$ +- $0 \leq a,b,c \leq N-1$ +- They are all integers. +@{lang.ja} +- $1 \leq N \leq @{param.N_MAX}$ +- $1 \leq M \leq @{param.M_MAX}$ +- $|x _ i|, |y _ i| \leq @{param.X_AND_Y_ABS_MAX}$ +- $|p _ i|, |q _ i| \leq @{param.X_AND_Y_ABS_MAX}$ +- $1 \leq Q \leq @{param.Q_MAX}$ +- $0 \leq a,b,c \leq N-1$ +- これらはすべて整数 +@{lang.end} + +## @{keyword.input} + +``` +$N$ +$x _ 0$ $y _ 0$ +$x _ 1$ $y _ 1$ +$\ \vdots$ +$x _ {N-1}$ $y _ {N-1}$ +$M$ +$p _ 0$ $q _ 0$ +$p _ 1$ $q _ 1$ +$\ \vdots$ +$p _ {M-1}$ $q_{M-1}$ +$Q$ +$a$ $b$ $c$ +$\ \vdots$ +$a$ $b$ $c$ +``` + +## @{keyword.sample} + +@{example.example_00} diff --git a/geo/count_points_in_triangle/verifier.cpp b/geo/count_points_in_triangle/verifier.cpp new file mode 100644 index 000000000..e67a52c77 --- /dev/null +++ b/geo/count_points_in_triangle/verifier.cpp @@ -0,0 +1,35 @@ +#include "testlib.h" +#include "params.h" + +int main() { + registerValidation(); + + int n = inf.readInt(1, N_MAX); + inf.readChar('\n'); + for (int i = 0; i < n; i++) { + inf.readInt(-X_AND_Y_ABS_MAX, X_AND_Y_ABS_MAX); + inf.readChar(' '); + inf.readInt(-X_AND_Y_ABS_MAX, X_AND_Y_ABS_MAX); + inf.readChar('\n'); + } + int m = inf.readInt(1, M_MAX); + inf.readChar('\n'); + for (int i = 0; i < m; i++) { + inf.readInt(-X_AND_Y_ABS_MAX, X_AND_Y_ABS_MAX); + inf.readChar(' '); + inf.readInt(-X_AND_Y_ABS_MAX, X_AND_Y_ABS_MAX); + inf.readChar('\n'); + } + int q = inf.readInt(1, Q_MAX); + inf.readChar('\n'); + for (int i = 0; i < q; i++) { + inf.readInt(0, n-1); + inf.readChar(' '); + inf.readInt(0, n-1); + inf.readChar(' '); + inf.readInt(0, n-1); + inf.readChar('\n'); + } + inf.readEof(); + return 0; +} From 2019f013fff2f8bfc3b5766d1b0ae5f25049bf6a Mon Sep 17 00:00:00 2001 From: Nachia Vivias Date: Wed, 27 Dec 2023 23:19:09 +0900 Subject: [PATCH 2/4] [count_points_in_triangle] add fast.cpp --- geo/count_points_in_triangle/info.toml | 2 + geo/count_points_in_triangle/sol/fast.cpp | 126 ++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 geo/count_points_in_triangle/sol/fast.cpp diff --git a/geo/count_points_in_triangle/info.toml b/geo/count_points_in_triangle/info.toml index 188baec58..069b30561 100644 --- a/geo/count_points_in_triangle/info.toml +++ b/geo/count_points_in_triangle/info.toml @@ -18,6 +18,8 @@ forum = "https://github.com/yosupo06/library-checker-problems/issues/908" [[solutions]] name = "naive.cpp" allow_tle = true +[[solutions]] + name = "fast.cpp" [params] diff --git a/geo/count_points_in_triangle/sol/fast.cpp b/geo/count_points_in_triangle/sol/fast.cpp new file mode 100644 index 000000000..fba04f50f --- /dev/null +++ b/geo/count_points_in_triangle/sol/fast.cpp @@ -0,0 +1,126 @@ +#include +#include +#include +#include + +template +struct VecI2 { + Int x, y; + VecI2() : x(0), y(0) {} + VecI2(Int _x, Int _y) : x(_x), y(_y) {} + VecI2 operator+(VecI2 r) const { return VecI2(x+r.x, y+r.y); } + VecI2 operator-(VecI2 r) const { return VecI2(x-r.x, y-r.y); } + VecI2 operator-() const { return VecI2(-x, -y); } + Int2 operator*(VecI2 r) const { return Int2(x) * Int2(r.x) + Int2(y) * Int2(r.y); } + Int2 operator^(VecI2 r) const { return Int2(x) * Int2(r.y) - Int2(y) * Int2(r.x); } + static bool compareYX(VecI2 a, VecI2 b){ return a.y < b.y || (!(b.y < a.y) && a.x < b.x); } + static bool compareXY(VecI2 a, VecI2 b){ return a.x < b.x || (!(b.x < a.x) && a.y < b.y); } +}; + + +using i64 = long long; +using namespace std; +using Vec = VecI2; +#define rep(i,n) for(int i=0; i<(int)(n); i++) + +int main(){ + int N; scanf("%d", &N); + vector A(N); + rep(i,N) scanf("%lld%lld", &A[i].x, &A[i].y); + int M; scanf("%d", &M); + vector B(M); + rep(i,M) scanf("%lld%lld", &B[i].x, &B[i].y); + + auto pointL = vector(N); // bx < Ax + auto pointM = vector(N); // bx = Ax + rep(i,N) rep(j,M) if(A[i].y == B[j].y){ + if(B[j].x < A[i].x) pointL[i]++; + if(B[j].x == A[i].x) pointM[i]++; + } + + auto edgeL = vector>(N, vector(N)); // bx < lerp(Ax, Bx) + auto edgeM = vector>(N, vector(N)); // bx = lerp(Ax, Bx) + rep(a,N){ + struct PointId { int i; int c; Vec v; }; + vector points; + rep(b,N) if(A[a].y < A[b].y) points.push_back({ b, 0, A[b] - A[a] }); + rep(b,M) if(A[a].y < B[b].y) points.push_back({ b, 1, B[b] - A[a] }); + rep(b,N) if(A[a].y < A[b].y) points.push_back({ b, 2, A[b] - A[a] }); + sort(points.begin(), points.end(), [&](const PointId& l, const PointId& r){ + i64 det = l.v ^ r.v; + if(det != 0) return det < 0; + return l.c < r.c; + }); + int qN = points.size(); + vector queryOrd(qN); rep(i,qN) queryOrd[i] = i; + sort(queryOrd.begin(), queryOrd.end(), [&](int l, int r){ + return make_pair(points[l].v.y, points[l].c%2) < make_pair(points[r].v.y, points[r].c%2); + }); + vector BIT(qN); + for(int qi=0; qi 0){ buf += BIT[p-1]; p -= p & -p; } + edgeL[a][points[q].i] = buf; + } else if(points[q].c == 1) { + int p = q+1; + while(p <= qN){ BIT[p-1]++; p += p & -p; } + } else { + int buf = 0; + int p = q+1; + while(p > 0){ buf += BIT[p-1]; p -= p & -p; } + edgeM[a][points[q].i] = buf; + } + } + rep(b,N) edgeM[a][b] -= edgeL[a][b]; + } + + int Q; scanf("%d", &Q); + rep(qi, Q){ + int a,b,c; scanf("%d%d%d", &a, &b, &c); + if(Vec::compareYX(A[b], A[a])) swap(a, b); + if(Vec::compareYX(A[c], A[b])) swap(b, c); + if(Vec::compareYX(A[b], A[a])) swap(a, b); + // c ^y + // b | + // a +---> x + + // c + // nega | + // v posi + // a + auto det = (A[a] - A[c]) ^ (A[b] - A[c]); + int ans = 0; + if(det != 0){ + if(A[a].y == A[b].y){ // A[a].x < A[b].x + // c + // a b + ans = edgeL[b][c] - (edgeL[a][c] + edgeM[a][c]); + } else if(A[b].y == A[c].y){ // A[b].x < A[c].x + // b c + // a + ans = edgeL[a][c] - (edgeL[a][b] + edgeM[a][b]); + } else if(det < 0){ + // c + // b + // a + ans += edgeL[a][c]; + ans -= edgeL[b][c] + edgeM[b][c]; + ans -= edgeL[a][b] + edgeM[a][b]; + ans -= pointL[b] + pointM[b]; + } else { + // c + // b + // a + ans += edgeL[a][b]; + ans += edgeL[b][c]; + ans += pointL[b]; + ans -= edgeL[a][c] + edgeM[a][c]; + } + } + printf("%d\n", ans); + } + return 0; +} From e38c6f61c631dc91db95872902526eb741e0def9 Mon Sep 17 00:00:00 2001 From: Nachia Vivias Date: Wed, 27 Dec 2023 23:49:33 +0900 Subject: [PATCH 3/4] [count_points_in_triangle] import fastio --- geo/count_points_in_triangle/sol/correct.cpp | 19 +- geo/count_points_in_triangle/sol/fast.cpp | 18 +- geo/count_points_in_triangle/sol/fastio.hpp | 208 +++++++++++++++++++ geo/count_points_in_triangle/sol/naive.cpp | 21 +- 4 files changed, 239 insertions(+), 27 deletions(-) create mode 100644 geo/count_points_in_triangle/sol/fastio.hpp diff --git a/geo/count_points_in_triangle/sol/correct.cpp b/geo/count_points_in_triangle/sol/correct.cpp index c1e9fa946..0105eac24 100644 --- a/geo/count_points_in_triangle/sol/correct.cpp +++ b/geo/count_points_in_triangle/sol/correct.cpp @@ -1,5 +1,4 @@ - -#include +#include "fastio.hpp" #include #include #include @@ -25,12 +24,14 @@ using Vec = VecI2; #define rep(i,n) for(int i=0; i<(int)(n); i++) int main(){ - int N; scanf("%d", &N); + using nachia::cin; + using nachia::cout; + int N; cin >> N; vector A(N); - rep(i,N) scanf("%lld%lld", &A[i].x, &A[i].y); - int M; scanf("%d", &M); + rep(i,N) cin >> A[i].x >> A[i].y; + int M; cin >> M; vector B(M); - rep(i,M) scanf("%lld%lld", &B[i].x, &B[i].y); + rep(i,M) cin >> B[i].x >> B[i].y; auto pointL = vector(N); // bx < Ax auto pointM = vector(N); // bx = Ax @@ -49,9 +50,9 @@ int main(){ } } - int Q; scanf("%d", &Q); + int Q; cin >> Q; rep(qi, Q){ - int a,b,c; scanf("%d%d%d", &a, &b, &c); + int a,b,c; cin >> a >> b >> c; if(Vec::compareYX(A[b], A[a])) swap(a, b); if(Vec::compareYX(A[c], A[b])) swap(b, c); if(Vec::compareYX(A[b], A[a])) swap(a, b); @@ -92,7 +93,7 @@ int main(){ ans -= edgeL[a][c] + edgeM[a][c]; } } - printf("%d\n", ans); + cout << ans << '\n'; } return 0; } diff --git a/geo/count_points_in_triangle/sol/fast.cpp b/geo/count_points_in_triangle/sol/fast.cpp index fba04f50f..13886c602 100644 --- a/geo/count_points_in_triangle/sol/fast.cpp +++ b/geo/count_points_in_triangle/sol/fast.cpp @@ -1,4 +1,4 @@ -#include +#include "fastio.hpp" #include #include #include @@ -24,12 +24,14 @@ using Vec = VecI2; #define rep(i,n) for(int i=0; i<(int)(n); i++) int main(){ - int N; scanf("%d", &N); + using nachia::cin; + using nachia::cout; + int N; cin >> N; vector A(N); - rep(i,N) scanf("%lld%lld", &A[i].x, &A[i].y); - int M; scanf("%d", &M); + rep(i,N) cin >> A[i].x >> A[i].y; + int M; cin >> M; vector B(M); - rep(i,M) scanf("%lld%lld", &B[i].x, &B[i].y); + rep(i,M) cin >> B[i].x >> B[i].y; auto pointL = vector(N); // bx < Ax auto pointM = vector(N); // bx = Ax @@ -77,9 +79,9 @@ int main(){ rep(b,N) edgeM[a][b] -= edgeL[a][b]; } - int Q; scanf("%d", &Q); + int Q; cin >> Q; rep(qi, Q){ - int a,b,c; scanf("%d%d%d", &a, &b, &c); + int a,b,c; cin >> a >> b >> c; if(Vec::compareYX(A[b], A[a])) swap(a, b); if(Vec::compareYX(A[c], A[b])) swap(b, c); if(Vec::compareYX(A[b], A[a])) swap(a, b); @@ -120,7 +122,7 @@ int main(){ ans -= edgeL[a][c] + edgeM[a][c]; } } - printf("%d\n", ans); + cout << ans << '\n'; } return 0; } diff --git a/geo/count_points_in_triangle/sol/fastio.hpp b/geo/count_points_in_triangle/sol/fastio.hpp new file mode 100644 index 000000000..d0981a5bb --- /dev/null +++ b/geo/count_points_in_triangle/sol/fastio.hpp @@ -0,0 +1,208 @@ +#pragma once +#include +#include +#include +#include + +namespace nachia{ + +struct CInStream{ +private: + static const unsigned int INPUT_BUF_SIZE = 1 << 17; + unsigned int p = INPUT_BUF_SIZE; + static char Q[INPUT_BUF_SIZE]; +public: + using MyType = CInStream; + char seekChar(){ + if(p == INPUT_BUF_SIZE){ + size_t len = fread(Q, 1, INPUT_BUF_SIZE, stdin); + if(len != INPUT_BUF_SIZE) Q[len] = '\0'; + p = 0; + } + return Q[p]; + } + void skipSpace(){ while(isspace(seekChar())) p++; } +private: + template + T nextUInt(){ + if constexpr (sp) skipSpace(); + T buf = 0; + while(true){ + char tmp = seekChar(); + if('9' < tmp || tmp < '0') break; + buf = buf * 10 + (tmp - '0'); + p++; + } + return buf; + } +public: + uint32_t nextU32(){ return nextUInt(); } + int32_t nextI32(){ + skipSpace(); + if(seekChar() == '-'){ + p++; return (int32_t)(-nextUInt()); + } + return (int32_t)nextUInt(); + } + uint64_t nextU64(){ return nextUInt();} + int64_t nextI64(){ + skipSpace(); + if(seekChar() == '-'){ + p++; return (int64_t)(-nextUInt()); + } + return (int64_t)nextUInt(); + } + template + T nextInt(){ + skipSpace(); + if(seekChar() == '-'){ + p++; + return - nextUInt(); + } + return nextUInt(); + } + char nextChar(){ skipSpace(); char buf = seekChar(); p++; return buf; } + std::string nextToken(){ + skipSpace(); + std::string buf; + while(true){ + char ch = seekChar(); + if(isspace(ch) || ch == '\0') break; + buf.push_back(ch); + p++; + } + return buf; + } + MyType& operator>>(unsigned int& dest){ dest = nextU32(); return *this; } + MyType& operator>>(int& dest){ dest = nextI32(); return *this; } + MyType& operator>>(unsigned long& dest){ dest = nextU64(); return *this; } + MyType& operator>>(long& dest){ dest = nextI64(); return *this; } + MyType& operator>>(unsigned long long& dest){ dest = nextU64(); return *this; } + MyType& operator>>(long long& dest){ dest = nextI64(); return *this; } + MyType& operator>>(std::string& dest){ dest = nextToken(); return *this; } + MyType& operator>>(char& dest){ dest = nextChar(); return *this; } +} cin; + +struct FastOutputTable{ + char LZ[1000][4] = {}; + char NLZ[1000][4] = {}; + constexpr FastOutputTable(){ + using u32 = uint_fast32_t; + for(u32 d=0; d<1000; d++){ + LZ[d][0] = ('0' + d / 100 % 10); + LZ[d][1] = ('0' + d / 10 % 10); + LZ[d][2] = ('0' + d / 1 % 10); + LZ[d][3] = '\0'; + } + for(u32 d=0; d<1000; d++){ + u32 i = 0; + if(d >= 100) NLZ[d][i++] = ('0' + d / 100 % 10); + if(d >= 10) NLZ[d][i++] = ('0' + d / 10 % 10); + if(d >= 1) NLZ[d][i++] = ('0' + d / 1 % 10); + NLZ[d][i++] = '\0'; + } + } +}; + +struct COutStream{ +private: + using u32 = uint32_t; + using u64 = uint64_t; + using MyType = COutStream; + static const u32 OUTPUT_BUF_SIZE = 1 << 17; + static char Q[OUTPUT_BUF_SIZE]; + static constexpr FastOutputTable TB = FastOutputTable(); + u32 p = 0; + static constexpr u32 P10(u32 d){ return d ? P10(d-1)*10 : 1; } + static constexpr u64 P10L(u32 d){ return d ? P10L(d-1)*10 : 1; } + template static void Fil(T& m, U& l, U x){ m = l/x; l -= m*x; } + void next_dig9(u32 x){ + u32 y; + Fil(y, x, P10(6)); + nextCstr(TB.LZ[y]); + Fil(y, x, P10(3)); + nextCstr(TB.LZ[y]); nextCstr(TB.LZ[x]); + } +public: + void nextChar(char c){ + Q[p++] = c; + if(p == OUTPUT_BUF_SIZE){ fwrite(Q, p, 1, stdout); p = 0; } + } + void nextEoln(){ nextChar('\n'); } + void nextCstr(const char* s){ while(*s) nextChar(*(s++)); } + void nextU32(uint32_t x){ + u32 y = 0; + if(x >= P10(9)){ + Fil(y, x, P10(9)); + nextCstr(TB.NLZ[y]); next_dig9(x); + } + else if(x >= P10(6)){ + Fil(y, x, P10(6)); + nextCstr(TB.NLZ[y]); + Fil(y, x, P10(3)); + nextCstr(TB.LZ[y]); nextCstr(TB.LZ[x]); + } + else if(x >= P10(3)){ + Fil(y, x, P10(3)); + nextCstr(TB.NLZ[y]); nextCstr(TB.LZ[x]); + } + else if(x >= 1) nextCstr(TB.NLZ[x]); + else nextChar('0'); + } + void nextI32(int32_t x){ + if(x >= 0) nextU32(x); + else{ nextChar('-'); nextU32((u32)-x); } + } + void nextU64(uint64_t x){ + u32 y = 0; + if(x >= P10L(18)){ + Fil(y, x, P10L(18)); + nextU32(y); + Fil(y, x, P10L(9)); + next_dig9(y); next_dig9(x); + } + else if(x >= P10L(9)){ + Fil(y, x, P10L(9)); + nextU32(y); next_dig9(x); + } + else nextU32(x); + } + void nextI64(int64_t x){ + if(x >= 0) nextU64(x); + else{ nextChar('-'); nextU64((u64)-x); } + } + template + void nextInt(T x){ + if(x < 0){ nextChar('-'); x = -x; } + if(!(0 < x)){ nextChar('0'); return; } + std::string buf; + while(0 < x){ + buf.push_back('0' + (int)(x % 10)); + x /= 10; + } + for(int i=(int)buf.size()-1; i>=0; i--){ + nextChar(buf[i]); + } + } + void writeToFile(bool flush = false){ + fwrite(Q, p, 1, stdout); + if(flush) fflush(stdout); + p = 0; + } + COutStream(){ Q[0] = 0; } + ~COutStream(){ writeToFile(); } + MyType& operator<<(unsigned int tg){ nextU32(tg); return *this; } + MyType& operator<<(unsigned long tg){ nextU64(tg); return *this; } + MyType& operator<<(unsigned long long tg){ nextU64(tg); return *this; } + MyType& operator<<(int tg){ nextI32(tg); return *this; } + MyType& operator<<(long tg){ nextI64(tg); return *this; } + MyType& operator<<(long long tg){ nextI64(tg); return *this; } + MyType& operator<<(const std::string& tg){ nextCstr(tg.c_str()); return *this; } + MyType& operator<<(const char* tg){ nextCstr(tg); return *this; } + MyType& operator<<(char tg){ nextChar(tg); return *this; } +} cout; + +char CInStream::Q[INPUT_BUF_SIZE]; +char COutStream::Q[OUTPUT_BUF_SIZE]; + +} // namespace nachia diff --git a/geo/count_points_in_triangle/sol/naive.cpp b/geo/count_points_in_triangle/sol/naive.cpp index ef3a5d4d5..3deda9c57 100644 --- a/geo/count_points_in_triangle/sol/naive.cpp +++ b/geo/count_points_in_triangle/sol/naive.cpp @@ -1,5 +1,4 @@ - -#include +#include "fastio.hpp" #include #include using i64 = long long; @@ -7,22 +6,24 @@ using i64 = long long; int main(){ using namespace std; - int N; scanf("%d", &N); + using nachia::cin; + using nachia::cout; + int N; cin >> N; vector Ax(N), Ay(N); - rep(i,N) scanf("%lld%lld", &Ax[i], &Ay[i]); - int M; scanf("%d", &M); + rep(i,N) cin >> Ax[i] >> Ay[i]; + int M; cin >> M; vector Bx(M), By(M); - rep(i,M) scanf("%lld%lld", &Bx[i], &By[i]); + rep(i,M) cin >> Bx[i] >> By[i]; - int Q; scanf("%d", &Q); + int Q; cin >> Q; rep(qi, Q){ - int a,b,c; scanf("%d%d%d", &a, &b, &c); + int a,b,c; cin >> a >> b >> c; i64 xab = Ax[b] - Ax[a]; i64 yab = Ay[b] - Ay[a]; i64 xac = Ax[c] - Ax[a]; i64 yac = Ay[c] - Ay[a]; if(xab * yac - yab * xac == 0){ - printf("0\n"); + cout << "0\n"; continue; } if(xab * yac - yab * xac < 0){ @@ -52,7 +53,7 @@ int main(){ } if(ok) ans++; } - printf("%d\n", ans); + cout << ans << '\n'; } return 0; } From a81282da72d541dc085b9494c72e7a93f75ae885 Mon Sep 17 00:00:00 2001 From: Nachia Vivias Date: Thu, 28 Dec 2023 00:20:20 +0900 Subject: [PATCH 4/4] [count_points_in_triangle] brushup --- .../gen/{dence.cpp => dense.cpp} | 2 +- geo/count_points_in_triangle/gen/max_random.cpp | 2 +- geo/count_points_in_triangle/gen/middle_random.cpp | 9 ++++++++- geo/count_points_in_triangle/hash.json | 8 ++++---- geo/count_points_in_triangle/info.toml | 2 +- geo/count_points_in_triangle/sol/correct.cpp | 8 ++++++++ geo/count_points_in_triangle/sol/fast.cpp | 8 ++++++++ geo/count_points_in_triangle/sol/naive.cpp | 8 ++++++++ geo/count_points_in_triangle/task.md | 4 ++-- 9 files changed, 41 insertions(+), 10 deletions(-) rename geo/count_points_in_triangle/gen/{dence.cpp => dense.cpp} (97%) diff --git a/geo/count_points_in_triangle/gen/dence.cpp b/geo/count_points_in_triangle/gen/dense.cpp similarity index 97% rename from geo/count_points_in_triangle/gen/dence.cpp rename to geo/count_points_in_triangle/gen/dense.cpp index 841ad459f..ba013b27c 100644 --- a/geo/count_points_in_triangle/gen/dence.cpp +++ b/geo/count_points_in_triangle/gen/dense.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "../params.h" diff --git a/geo/count_points_in_triangle/gen/max_random.cpp b/geo/count_points_in_triangle/gen/max_random.cpp index 50bbdb7fd..8df33d48a 100644 --- a/geo/count_points_in_triangle/gen/max_random.cpp +++ b/geo/count_points_in_triangle/gen/max_random.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "../params.h" diff --git a/geo/count_points_in_triangle/gen/middle_random.cpp b/geo/count_points_in_triangle/gen/middle_random.cpp index 4724029a7..739f6742b 100644 --- a/geo/count_points_in_triangle/gen/middle_random.cpp +++ b/geo/count_points_in_triangle/gen/middle_random.cpp @@ -1,4 +1,11 @@ -#include + +/* + +An easier solution ( O( N + M Q ) time ) can pass this testcase. + +*/ + +#include #include #include "../params.h" diff --git a/geo/count_points_in_triangle/hash.json b/geo/count_points_in_triangle/hash.json index 073e69b1f..99ed58eec 100644 --- a/geo/count_points_in_triangle/hash.json +++ b/geo/count_points_in_triangle/hash.json @@ -1,8 +1,8 @@ { - "dence_00.in": "036f55e2799522e6368dc78fbef79e2822b4bb70ecc8541702f1fe5cb712a09f", - "dence_00.out": "464ed740e3d66104017ab38cb686f86b9958a1bbc8a8a0fd68496b1047c2075b", - "dence_01.in": "922fc5c5ca06f32d650f7164ba045641fd036b4b0c4725b767c6d4849dff3ef5", - "dence_01.out": "a7e3f7722d143d68eb9642fa64b030e1d46a7726b03dea96735298aea5c1211b", + "dense_00.in": "036f55e2799522e6368dc78fbef79e2822b4bb70ecc8541702f1fe5cb712a09f", + "dense_00.out": "464ed740e3d66104017ab38cb686f86b9958a1bbc8a8a0fd68496b1047c2075b", + "dense_01.in": "922fc5c5ca06f32d650f7164ba045641fd036b4b0c4725b767c6d4849dff3ef5", + "dense_01.out": "a7e3f7722d143d68eb9642fa64b030e1d46a7726b03dea96735298aea5c1211b", "example_00.in": "1c1694bc76fbc885dc663f31749118c55f44de16e2c55694e6b716f9f72d409a", "example_00.out": "49f044318460c78482da423fe4ce239bace57b06a491ad9b3e3a4d0714677955", "max_random_00.in": "d2a0b5d592650f276a858f20eacc2046aa7ae6393dbe72e61a95305771c2adcc", diff --git a/geo/count_points_in_triangle/info.toml b/geo/count_points_in_triangle/info.toml index 069b30561..26c3a7d7d 100644 --- a/geo/count_points_in_triangle/info.toml +++ b/geo/count_points_in_triangle/info.toml @@ -12,7 +12,7 @@ forum = "https://github.com/yosupo06/library-checker-problems/issues/908" name = "max_random.cpp" number = 2 [[tests]] - name = "dence.cpp" + name = "dense.cpp" number = 2 [[solutions]] diff --git a/geo/count_points_in_triangle/sol/correct.cpp b/geo/count_points_in_triangle/sol/correct.cpp index 0105eac24..0b08fec8c 100644 --- a/geo/count_points_in_triangle/sol/correct.cpp +++ b/geo/count_points_in_triangle/sol/correct.cpp @@ -1,3 +1,11 @@ +/* + +O( N^2 M + Q ) time solution + +too slow at N,M = 1000 + +*/ + #include "fastio.hpp" #include #include diff --git a/geo/count_points_in_triangle/sol/fast.cpp b/geo/count_points_in_triangle/sol/fast.cpp index 13886c602..87c4e7da4 100644 --- a/geo/count_points_in_triangle/sol/fast.cpp +++ b/geo/count_points_in_triangle/sol/fast.cpp @@ -1,3 +1,11 @@ +/* + +O( N M log( N M ) + Q ) time solution + +not so fast at N,M = 1000 + +*/ + #include "fastio.hpp" #include #include diff --git a/geo/count_points_in_triangle/sol/naive.cpp b/geo/count_points_in_triangle/sol/naive.cpp index 3deda9c57..f7209ea28 100644 --- a/geo/count_points_in_triangle/sol/naive.cpp +++ b/geo/count_points_in_triangle/sol/naive.cpp @@ -1,3 +1,11 @@ +/* + +O( N + M Q ) time solution + +can be accepted at N,M=500 and Q=10**6 + +*/ + #include "fastio.hpp" #include #include diff --git a/geo/count_points_in_triangle/task.md b/geo/count_points_in_triangle/task.md index 774b6ed6f..f0eb7f8c5 100644 --- a/geo/count_points_in_triangle/task.md +++ b/geo/count_points_in_triangle/task.md @@ -19,7 +19,7 @@ Given 2D-points $A _ k=(x _ k, y _ k)$ $(k=0,1,\ldots ,N-1)$ and 2D-points $B _ - $|x _ i|, |y _ i| \leq @{param.X_AND_Y_ABS_MAX}$ - $|p _ i|, |q _ i| \leq @{param.X_AND_Y_ABS_MAX}$ - $1 \leq Q \leq @{param.Q_MAX}$ -- $0 \leq a,b,c \leq N-1$ +- $0 \leq a,b,c \lt N$ - They are all integers. @{lang.ja} - $1 \leq N \leq @{param.N_MAX}$ @@ -27,7 +27,7 @@ Given 2D-points $A _ k=(x _ k, y _ k)$ $(k=0,1,\ldots ,N-1)$ and 2D-points $B _ - $|x _ i|, |y _ i| \leq @{param.X_AND_Y_ABS_MAX}$ - $|p _ i|, |q _ i| \leq @{param.X_AND_Y_ABS_MAX}$ - $1 \leq Q \leq @{param.Q_MAX}$ -- $0 \leq a,b,c \leq N-1$ +- $0 \leq a,b,c \lt N$ - これらはすべて整数 @{lang.end}