diff --git a/datastructure/rectangle_add_point_get/checker.cpp b/datastructure/rectangle_add_point_get/checker.cpp new file mode 100644 index 000000000..6a66d5330 --- /dev/null +++ b/datastructure/rectangle_add_point_get/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/datastructure/rectangle_add_point_get/gen/example_00.in b/datastructure/rectangle_add_point_get/gen/example_00.in new file mode 100644 index 000000000..580df4e4d --- /dev/null +++ b/datastructure/rectangle_add_point_get/gen/example_00.in @@ -0,0 +1,14 @@ +4 9 +1 2 2 3 1 +1 1 2 5 10 +2 2 5 5 100 +3 1 5 2 1000 +1 1 1 +1 1 2 +1 1 3 +1 2 1 +1 2 2 +1 2 3 +1 3 1 +1 3 2 +1 3 3 diff --git a/datastructure/rectangle_add_point_get/gen/example_01.in b/datastructure/rectangle_add_point_get/gen/example_01.in new file mode 100644 index 000000000..7fe97ecd1 --- /dev/null +++ b/datastructure/rectangle_add_point_get/gen/example_01.in @@ -0,0 +1,11 @@ +2 8 +1 2 2 3 1 +1 1 2 5 10 +1 1 2 +1 2 3 +0 1 1 3 3 100 +1 1 2 +1 2 3 +0 2 1 3 5 1000 +1 1 2 +1 2 3 diff --git a/datastructure/rectangle_add_point_get/gen/many_points.cpp b/datastructure/rectangle_add_point_get/gen/many_points.cpp new file mode 100644 index 000000000..a347fbc5b --- /dev/null +++ b/datastructure/rectangle_add_point_get/gen/many_points.cpp @@ -0,0 +1,44 @@ +#include +#include +#include "random.h" +#include "../params.h" + +using namespace std; + +tuple random_rect(Random& gen) { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + int w = gen.uniform(0, WEIGHT_MAX); + return {l, d, r, u, w}; +} + +pair random_pt(Random& gen) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + return {x, y}; +} + +int main(int, char** argv) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = N_MAX; + int q = Q_MAX; + printf("%d %d\n", n, q); + + for (int i = 0; i < n; i++) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d\n", l, d, r, u, w); + } + for (int i = 0; i < q; i++) { + bool rect = gen.uniform(0, 10) == 0; + if (rect) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d %d\n", 0, l, d, r, u, w); + } else { + auto [x, y] = random_pt(gen); + printf("%d %d %d\n", 1, x, y); + } + } + return 0; +} diff --git a/datastructure/rectangle_add_point_get/gen/many_rectangles.cpp b/datastructure/rectangle_add_point_get/gen/many_rectangles.cpp new file mode 100644 index 000000000..eea12d503 --- /dev/null +++ b/datastructure/rectangle_add_point_get/gen/many_rectangles.cpp @@ -0,0 +1,44 @@ +#include +#include +#include "random.h" +#include "../params.h" + +using namespace std; + +tuple random_rect(Random& gen) { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + int w = gen.uniform(0, WEIGHT_MAX); + return {l, d, r, u, w}; +} + +pair random_pt(Random& gen) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + return {x, y}; +} + +int main(int, char** argv) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = N_MAX; + int q = Q_MAX; + printf("%d %d\n", n, q); + + for (int i = 0; i < n; i++) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d\n", l, d, r, u, w); + } + for (int i = 0; i < q; i++) { + bool rect = gen.uniform(0, 10) > 0; + if (rect) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d %d\n", 0, l, d, r, u, w); + } else { + auto [x, y] = random_pt(gen); + printf("%d %d %d\n", 1, x, y); + } + } + return 0; +} diff --git a/datastructure/rectangle_add_point_get/gen/max_random.cpp b/datastructure/rectangle_add_point_get/gen/max_random.cpp new file mode 100644 index 000000000..dc0493ddb --- /dev/null +++ b/datastructure/rectangle_add_point_get/gen/max_random.cpp @@ -0,0 +1,44 @@ +#include +#include +#include "random.h" +#include "../params.h" + +using namespace std; + +tuple random_rect(Random& gen) { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + int w = gen.uniform(0, WEIGHT_MAX); + return {l, d, r, u, w}; +} + +pair random_pt(Random& gen) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + return {x, y}; +} + +int main(int, char** argv) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = N_MAX; + int q = Q_MAX; + printf("%d %d\n", n, q); + + for (int i = 0; i < n; i++) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d\n", l, d, r, u, w); + } + for (int i = 0; i < q; i++) { + int t = gen.uniform(0, 1); + if (t == 0) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d %d\n", 0, l, d, r, u, w); + } else { + auto [x, y] = random_pt(gen); + printf("%d %d %d\n", 1, x, y); + } + } + return 0; +} diff --git a/datastructure/rectangle_add_point_get/gen/power_of_2.cpp b/datastructure/rectangle_add_point_get/gen/power_of_2.cpp new file mode 100644 index 000000000..c5f4e2abf --- /dev/null +++ b/datastructure/rectangle_add_point_get/gen/power_of_2.cpp @@ -0,0 +1,48 @@ +#include +#include +#include "random.h" +#include "../params.h" + +using namespace std; + +tuple random_rect(Random& gen) { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + int w = gen.uniform(0, WEIGHT_MAX); + return {l, d, r, u, w}; +} + +pair random_pt(Random& gen) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + return {x, y}; +} + +int main(int, char** argv) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = 1; + for (; n + n <= N_MAX; n <<= 1) + ; + int q = 1; + for (; q + q <= Q_MAX; q <<= 1) + ; + printf("%d %d\n", n, q); + + for (int i = 0; i < n; i++) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d\n", l, d, r, u, w); + } + for (int i = 0; i < q; i++) { + int t = gen.uniform(0, 1); + if (t == 0) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d %d\n", 0, l, d, r, u, w); + } else { + auto [x, y] = random_pt(gen); + printf("%d %d %d\n", 1, x, y); + } + } + return 0; +} diff --git a/datastructure/rectangle_add_point_get/gen/random.cpp b/datastructure/rectangle_add_point_get/gen/random.cpp new file mode 100644 index 000000000..5fed61427 --- /dev/null +++ b/datastructure/rectangle_add_point_get/gen/random.cpp @@ -0,0 +1,44 @@ +#include +#include +#include "random.h" +#include "../params.h" + +using namespace std; + +tuple random_rect(Random& gen) { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + int w = gen.uniform(0, WEIGHT_MAX); + return {l, d, r, u, w}; +} + +pair random_pt(Random& gen) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + return {x, y}; +} + +int main(int, char** argv) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = gen.uniform(1, N_MAX); + int q = gen.uniform(1, Q_MAX); + printf("%d %d\n", n, q); + + for (int i = 0; i < n; i++) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d\n", l, d, r, u, w); + } + for (int i = 0; i < q; i++) { + int t = gen.uniform(0, 1); + if (t == 0) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d %d\n", 0, l, d, r, u, w); + } else { + auto [x, y] = random_pt(gen); + printf("%d %d %d\n", 1, x, y); + } + } + return 0; +} diff --git a/datastructure/rectangle_add_point_get/gen/small.cpp b/datastructure/rectangle_add_point_get/gen/small.cpp new file mode 100644 index 000000000..684ebda01 --- /dev/null +++ b/datastructure/rectangle_add_point_get/gen/small.cpp @@ -0,0 +1,47 @@ +#include +#include +#include "random.h" +#include "../params.h" + +using namespace std; + +#define SMALL_N_MAX 1000 +#define SMALL_Q_MAX 1000 + +tuple random_rect(Random& gen) { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + int w = gen.uniform(0, WEIGHT_MAX); + return {l, d, r, u, w}; +} + +pair random_pt(Random& gen) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + return {x, y}; +} + +int main(int, char** argv) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = gen.uniform(1, SMALL_N_MAX); + int q = gen.uniform(1, SMALL_Q_MAX); + printf("%d %d\n", n, q); + + for (int i = 0; i < n; i++) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d\n", l, d, r, u, w); + } + for (int i = 0; i < q; i++) { + int t = gen.uniform(0, 1); + if (t == 0) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d %d\n", 0, l, d, r, u, w); + } else { + auto [x, y] = random_pt(gen); + printf("%d %d %d\n", 1, x, y); + } + } + return 0; +} diff --git a/datastructure/rectangle_add_point_get/gen/small_coord.cpp b/datastructure/rectangle_add_point_get/gen/small_coord.cpp new file mode 100644 index 000000000..f79dc2f4b --- /dev/null +++ b/datastructure/rectangle_add_point_get/gen/small_coord.cpp @@ -0,0 +1,46 @@ +#include +#include +#include "random.h" +#include "../params.h" + +using namespace std; + +const int MAX = 50; + +tuple random_rect(Random& gen) { + auto [l, r] = gen.uniform_pair(0, MAX); + auto [d, u] = gen.uniform_pair(0, MAX); + int w = gen.uniform(0, WEIGHT_MAX); + return {l, d, r, u, w}; +} + +pair random_pt(Random& gen) { + int x = gen.uniform(0, MAX); + int y = gen.uniform(0, MAX); + return {x, y}; +} + +int main(int, char** argv) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = N_MAX; + int q = Q_MAX; + printf("%d %d\n", n, q); + + for (int i = 0; i < n; i++) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d\n", l, d, r, u, w); + } + for (int i = 0; i < q; i++) { + int t = gen.uniform(0, 1); + if (t == 0) { + auto [l, d, r, u, w] = random_rect(gen); + printf("%d %d %d %d %d %d\n", 0, l, d, r, u, w); + } else { + auto [x, y] = random_pt(gen); + printf("%d %d %d\n", 1, x, y); + } + } + return 0; +} diff --git a/datastructure/rectangle_add_point_get/hash.json b/datastructure/rectangle_add_point_get/hash.json new file mode 100644 index 000000000..6db63e213 --- /dev/null +++ b/datastructure/rectangle_add_point_get/hash.json @@ -0,0 +1,40 @@ +{ + "example_00.in": "9298a09e06398cf65918f9907bfc1b6e038916b3fcb46a10154f9ad3ac4ff46c", + "example_00.out": "b4a88223aad900a5bb864725830964385f454678f13746d29b1e38560e0d7d11", + "example_01.in": "0af03e46e344da2f5771fe6721e9ff87da1eb4037213bc32e64fe83452afb3b7", + "example_01.out": "3146db811253c21de7de9f0fbd371cde2081bcd99453a33ff8d873d9a6e0d1c3", + "many_points_00.in": "45b56d8ee3648e4d976cecad3f34f24f1aaef912a0ce69e8c667290b6e4a8431", + "many_points_00.out": "1b8ed157794dbc4094328d6c609afd17e25b48265cdf5c3531149e1078cf6bd4", + "many_rectangles_00.in": "e5cb7dfc4b57592056dd263ec691163420f65d0eee0f5b0b78c68570db25cda1", + "many_rectangles_00.out": "d054379efd4eca419af8b9f7d31a6bc19fe30f1603e582ce6c2ad170c9ca2321", + "max_random_00.in": "6183973f0afe20d3443ae700ff398765f23987cf3a0df0018f463d43e9e5d479", + "max_random_00.out": "2aef9d6c2ca2686a241705aa5a0368898027144e70e4227c24fadebca921664c", + "max_random_01.in": "883ccca6298a9c4dba27247c54f6218e05f73d40c83518adbcacad541729180c", + "max_random_01.out": "6f9fd18e62deb13747cd23bd32daf18a6215db65c388661050153ce888d65f7a", + "power_of_2_00.in": "17b837e61d44bf01c87492047134d829c06b5b55a82a2c23164bc402f8a91a90", + "power_of_2_00.out": "a81f9e94d1b3cc60829b4e99e4d175363a0fca871670ad9be4749e0676ebac12", + "power_of_2_01.in": "0262e96df11b0651b1e8857b05ddf610157bfd03b558d3d963ee956dbeb4c4c3", + "power_of_2_01.out": "5a1cc4a2ff3b2f4019eed33b8f390d31b8dfe301f8cddec6cf5d7af052c34d48", + "random_00.in": "2dc9a335fcfbb29dfd514ced7e9bc1551f94a2dd21da82e7307eec752d9e3f7c", + "random_00.out": "043a02d15cb3793ad3c79c5c55d3977f86b23992e43b93d2f9f34312a236ea1f", + "random_01.in": "970906b09a5b7355eae9cc9126d94b6593441702a14e616c9868e3c645909cf5", + "random_01.out": "7fab5546e20fc1f118163f6de12df57216aec93c81cdc2672b2198f5815e54c7", + "random_02.in": "1704eabaff693b8be667c46a363f3d130fd500e5a0304de12860a299d0e82a1c", + "random_02.out": "4b1dc4ce12c0c807dc4910eb050ffd0cc9c30f7547b4be8203f390de6e05c282", + "small_00.in": "40952eb562c8e7b305f6bbf66ba3b6f4b214617195e75892e34492bfdbd29f40", + "small_00.out": "1975a46f88ee2bda5db4078fec0f1827950cc82e84875c774a4f4403a11b2c92", + "small_01.in": "7f683cb4afe87e6f2833133b322faebccbc1124255dbccbbf294f11e653d751f", + "small_01.out": "931ed898c3df6ff99825119d1be4d5decb56253c26a7d1485e81a59dcabc090b", + "small_02.in": "fbc61acafe4ed9d3e668c5c84734638cc20defb8d0d5a047f97e3510355280a1", + "small_02.out": "426336b1cb157b575df0c0775139eb16c20923721f6b51555bfb02b99b48a49e", + "small_03.in": "c178b4ec2992dfc4f0278d705442026ab967157b3dacb17c3c32f08b0bb42fbd", + "small_03.out": "611faef0202f8ccaeed4a0d55d99e106782988896501fc74b3782e2e440d99d1", + "small_04.in": "b8f8a50bdc6aa3047692da6279e6c31ed5c61978b08f7c3bc2b8cea8b4f8e164", + "small_04.out": "b894958f102a886cab02e991f84334031e8e8805134304677d355cc45a1e9d0e", + "small_coord_00.in": "64aab4d1b54826243a2925e4e540eb4176a6aac82f23e66404a7f712f9c703f1", + "small_coord_00.out": "746fc1caca864bfeda6f438f63e0fdcd26e4c67b610b6d2adb2068233aca9f5d", + "small_coord_01.in": "f99f657344de70498d1fc5c8b7c06855f97bd6a333898c81b194021c629f4ad3", + "small_coord_01.out": "82fc5679024c4635e36a043e4a2eee2ac82e0cc7a4c61971d4246e6b66170896", + "small_coord_02.in": "93f4311db97a54fbdf211ba0ca5f2af13e05e2901fc4ad1de57a3dc38cb9edb7", + "small_coord_02.out": "9d6564c38fe516f182105b4af3aee45b9d86b99ce9313467f14132ca2810b487" +} \ No newline at end of file diff --git a/datastructure/rectangle_add_point_get/info.toml b/datastructure/rectangle_add_point_get/info.toml new file mode 100644 index 000000000..b0a20368c --- /dev/null +++ b/datastructure/rectangle_add_point_get/info.toml @@ -0,0 +1,41 @@ +title = 'Rectangle Add Point Get' +timelimit = 10.0 +forum = "https://github.com/yosupo06/library-checker-problems/issues/994" + +[[tests]] + name = "example.in" + number = 2 +[[tests]] + name = "small.cpp" + number = 5 +[[tests]] + name = "random.cpp" + number = 3 +[[tests]] + name = "max_random.cpp" + number = 2 +[[tests]] + name = "many_points.cpp" + number = 1 +[[tests]] + name = "many_rectangles.cpp" + number = 1 +[[tests]] + name = "small_coord.cpp" + number = 3 +[[tests]] + name = "power_of_2.cpp" + number = 2 + +[[solutions]] + name = "naive_1.cpp" + allow_re = true +[[solutions]] + name = "naive_2.cpp" + allow_re = true + +[params] + N_MAX = 100_000 + Q_MAX = 100_000 + COORD_MAX = 1000_000_000 + WEIGHT_MAX = 1000_000_000 diff --git a/datastructure/rectangle_add_point_get/sol/correct.cpp b/datastructure/rectangle_add_point_get/sol/correct.cpp new file mode 100644 index 000000000..170a5c112 --- /dev/null +++ b/datastructure/rectangle_add_point_get/sol/correct.cpp @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; + +using ll = long long; + +template +using vc = vector; +template +using vvc = vector>; + +#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_) +#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i) +#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i) +#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c)) +#define FOR1_R(a) for (ll i = (a)-1; i >= ll(0); --i) +#define FOR2_R(i, a) for (ll i = (a)-1; i >= ll(0); --i) +#define FOR3_R(i, a, b) for (ll i = (b)-1; i >= ll(a); --i) +#define overload4(a, b, c, d, e, ...) e +#define overload3(a, b, c, d, ...) d +#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__) +#define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__) + +#define all(x) x.begin(), x.end() +#define len(x) ll(x.size()) +#define elif else if + +#define eb emplace_back +#define mp make_pair +#define fi first +#define se second + +#define MIN(v) *min_element(all(v)) +#define MAX(v) *max_element(all(v)) +#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x))) +#define UNIQUE(x) \ + sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit() + +template +ll binary_search(F check, ll ok, ll ng, bool check_ok = true) { + if (check_ok) assert(check(ok)); + while (abs(ok - ng) > 1) { + auto x = (ng + ok) / 2; + (check(x) ? ok : ng) = x; + } + return ok; +} + +template +inline bool chmax(T &a, const S &b) { + return (a < b ? a = b, 1 : 0); +} +template +inline bool chmin(T &a, const S &b) { + return (a > b ? a = b, 1 : 0); +} + +// stable sort +template +vector argsort(const vector &A) { + vector ids(len(A)); + iota(all(ids), 0); + sort(all(ids), + [&](int i, int j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); }); + return ids; +} + +template +struct Monoid_Add { + using value_type = X; + static constexpr X op(const X &x, const X &y) noexcept { return x + y; } + static constexpr X inverse(const X &x) noexcept { return -x; } + static constexpr X power(const X &x, ll n) noexcept { return X(n) * x; } + static constexpr X unit() { return X(0); } + static constexpr bool commute = true; +}; + +template +struct FenwickTree_2D { + using G = Monoid; + using E = typename G::value_type; + static_assert(G::commute); + int N; + vc keyX; + XY min_X; + vc indptr; + vc keyY; + vc dat; + + FenwickTree_2D(vc &X, vc &Y, vc wt) { build(X, Y, wt); } + FenwickTree_2D(vc &X, vc &Y) { + vc wt(len(X), G::unit()); + build(X, Y, wt); + } + + inline int xtoi(XY x) { + return (SMALL_X ? clamp(x - min_X, 0, N) : LB(keyX, x)); + } + inline int nxt(int i) { return i + ((i + 1) & -(i + 1)); } + inline int prev(int i) { return i - ((i + 1) & -(i + 1)); } + + void build(vc &X, vc &Y, vc wt) { + assert(len(X) == len(Y) && len(X) == len(wt)); + if (!SMALL_X) { + keyX = X; + UNIQUE(keyX); + N = len(keyX); + } else { + min_X = (len(X) == 0 ? 0 : MIN(X)); + N = (len(X) == 0 ? 0 : MAX(X)) - min_X + 1; + keyX.resize(N); + FOR(i, N) keyX[i] = min_X + i; + } + vvc keyY_raw(N); + vvc dat_raw(N); + for (auto &&i: argsort(Y)) { + int ix = xtoi(X[i]); + XY y = Y[i]; + while (ix < N) { + auto &KY = keyY_raw[ix]; + if (len(KY) == 0 || KY.back() < y) { + KY.eb(y); + dat_raw[ix].eb(wt[i]); + } else { + dat_raw[ix].back() = G::op(dat_raw[ix].back(), wt[i]); + } + ix = nxt(ix); + } + } + + indptr.assign(N + 1, 0); + FOR(i, N) indptr[i + 1] = indptr[i] + len(keyY_raw[i]); + keyY.resize(indptr.back()); + dat.resize(indptr.back()); + FOR(i, N) FOR(j, indptr[i + 1] - indptr[i]) { + keyY[indptr[i] + j] = keyY_raw[i][j]; + dat[indptr[i] + j] = dat_raw[i][j]; + } + FOR(i, N) { + int n = indptr[i + 1] - indptr[i]; + FOR(j, n - 1) { + int k = nxt(j); + if (k < n) + dat[indptr[i] + k] = G::op(dat[indptr[i] + k], dat[indptr[i] + j]); + } + } + } + + void add(XY x, XY y, E val) { multiply(x, y, val); } + void multiply(XY x, XY y, E val) { + int i = xtoi(x); + assert(keyX[i] == x); + while (i < N) { multiply_i(i, y, val), i = nxt(i); } + } + + E sum(XY lx, XY rx, XY ly, XY ry) { return prod(lx, rx, ly, ry); } + E prod(XY lx, XY rx, XY ly, XY ry) { + E pos = G::unit(), neg = G::unit(); + int L = xtoi(lx) - 1, R = xtoi(rx) - 1; + while (L < R) { pos = G::op(pos, prod_i(R, ly, ry)), R = prev(R); } + while (R < L) { neg = G::op(neg, prod_i(L, ly, ry)), L = prev(L); } + return G::op(pos, G::inverse(neg)); + } + + E prefix_sum(XY rx, XY ry) { return prefix_prod(rx, ry); } + E prefix_prod(XY rx, XY ry) { + E pos = G::unit(); + int R = xtoi(rx) - 1; + while (R >= 0) { pos = G::op(pos, prefix_prod_i(R, ry)), R = prev(R); } + return pos; + } + +private: + void multiply_i(int i, XY y, E val) { + int LID = indptr[i], n = indptr[i + 1] - indptr[i]; + auto it = keyY.begin() + LID; + int j = lower_bound(it, it + n, y) - it; + while (j < n) { dat[LID + j] = G::op(dat[LID + j], val), j = nxt(j); } + } + + E prod_i(int i, XY ly, XY ry) { + E pos = G::unit(), neg = G::unit(); + int LID = indptr[i], n = indptr[i + 1] - indptr[i]; + auto it = keyY.begin() + LID; + int L = lower_bound(it, it + n, ly) - it - 1; + int R = lower_bound(it, it + n, ry) - it - 1; + while (L < R) { pos = G::op(pos, dat[LID + R]), R = prev(R); } + while (R < L) { neg = G::op(neg, dat[LID + L]), L = prev(L); } + return G::op(pos, G::inverse(neg)); + } + + E prefix_prod_i(int i, XY ry) { + E pos = G::unit(); + int LID = indptr[i], n = indptr[i + 1] - indptr[i]; + auto it = keyY.begin() + LID; + int R = lower_bound(it, it + n, ry) - it - 1; + while (R >= 0) { pos = G::op(pos, dat[LID + R]), R = prev(R); } + return pos; + } +}; + +int main() { + int N, Q; + scanf("%d %d", &N, &Q); + + using QT = tuple; + vc QUERY; + FOR(N) { + int x1, y1, x2, y2, w; + scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &w); + QUERY.eb(x1, x2, y1, y2, w); + } + + FOR(Q) { + int t; + scanf("%d", &t); + if (t == 0) { + int x1, y1, x2, y2, w; + scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &w); + QUERY.eb(x1, x2, y1, y2, w); + } else { + int x, y; + scanf("%d %d", &x, &y); + QUERY.eb(-1, x, y, 0, 0); + } + } + + vc X, Y; + for (auto &[x1, x2, y1, y2, w]: QUERY) { + if (x1 == -1) continue; + X.eb(x1), Y.eb(y1); + X.eb(x1), Y.eb(y2); + X.eb(x2), Y.eb(y1); + X.eb(x2), Y.eb(y2); + } + + FenwickTree_2D, int> bit(X, Y); + + for (auto &[x1, x2, y1, y2, w]: QUERY) { + if (x1 == -1) { + int x = x2, y = y1; + ll ans = bit.prefix_sum(x + 1, y + 1); + printf("%lld\n", ans); + } else { + bit.add(x1, y1, +w); + bit.add(x1, y2, -w); + bit.add(x2, y1, -w); + bit.add(x2, y2, +w); + } + } + + return 0; +} diff --git a/datastructure/rectangle_add_point_get/sol/naive_1.cpp b/datastructure/rectangle_add_point_get/sol/naive_1.cpp new file mode 100644 index 000000000..b498c85f8 --- /dev/null +++ b/datastructure/rectangle_add_point_get/sol/naive_1.cpp @@ -0,0 +1,41 @@ +#include +#include +#include +#include + +using namespace std; +using ll = long long; + +int main() { + int N, Q; + scanf("%d %d", &N, &Q); + assert(N + Q < 10000); + + vector> RECT; + for (int i = 0; i < N; ++i) { + int x1, x2, y1, y2, w; + scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &w); + RECT.emplace_back(x1, x2, y1, y2, w); + } + + for (int i = 0; i < Q; ++i) { + int t; + scanf("%d", &t); + if (t == 0) { + int x1, x2, y1, y2, w; + scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &w); + RECT.emplace_back(x1, x2, y1, y2, w); + } + if (t == 1) { + int x, y; + scanf("%d %d", &x, &y); + ll ans = 0; + for (auto& [x1, x2, y1, y2, w]: RECT) { + if (x1 <= x && x < x2 && y1 <= y && y < y2) { ans += w; } + } + printf("%lld\n", ans); + } + } + + return 0; +} diff --git a/datastructure/rectangle_add_point_get/sol/naive_2.cpp b/datastructure/rectangle_add_point_get/sol/naive_2.cpp new file mode 100644 index 000000000..bf316f8b9 --- /dev/null +++ b/datastructure/rectangle_add_point_get/sol/naive_2.cpp @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +using namespace std; +using ll = long long; + +const int MAX = 50; +ll A[MAX][MAX]; + +int main() { + int N, Q; + scanf("%d %d", &N, &Q); + + auto add = [&](int x1, int x2, int y1, int y2, int w) -> void { + assert(x2 <= MAX && y2 <= MAX); + for (int x = x1; x < x2; ++x) { + for (int y = y1; y < y2; ++y) { A[x][y] += w; } + } + }; + + for (int i = 0; i < N; ++i) { + int x1, x2, y1, y2, w; + scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &w); + add(x1, x2, y1, y2, w); + } + + for (int i = 0; i < Q; ++i) { + int t; + scanf("%d", &t); + if (t == 0) { + int x1, x2, y1, y2, w; + scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &w); + add(x1, x2, y1, y2, w); + } + if (t == 1) { + int x, y; + scanf("%d %d", &x, &y); + ll ans = 0; + if (x < MAX && y < MAX) ans = A[x][y]; + printf("%lld\n", ans); + } + } + + return 0; +} diff --git a/datastructure/rectangle_add_point_get/task.md b/datastructure/rectangle_add_point_get/task.md new file mode 100644 index 000000000..1e97768bc --- /dev/null +++ b/datastructure/rectangle_add_point_get/task.md @@ -0,0 +1,62 @@ +## @{keyword.statement} +@{lang.en} +You are given $N$ weighted rectangles on two-dimensional plane. +The position of $i$-th rectangle is +$$[l_i,r_i) \times [d_i,u_i) = \{(x,y)\in \mathbb{R}^2\mid l_i\leq x