diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/checker.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/checker.cpp new file mode 100644 index 00000000..6a66d533 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/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/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/example_00.in b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/example_00.in new file mode 100644 index 00000000..308fff9d --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/example_00.in @@ -0,0 +1,11 @@ +3 7 +2 0 1 +6 2 10 +5 4 100 +2 1 1 7 7 +0 5 6 1000 +0 5 1 10000 +3 1 5 7 7 0 100000 +1 1 1000000 +2 5 4 7 5 +2 5 1 7 7 diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/gen_random.py b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/gen_random.py new file mode 100644 index 00000000..e476d3f6 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/gen_random.py @@ -0,0 +1,70 @@ +#!/usr/bin/python3 + +import random as rd +import argparse as agp + +parser = agp.ArgumentParser(description="Generate a random test case.") + +parser.add_argument('N_MAX', type=int, help='Number of initial points.') +parser.add_argument('Q_MAX', type=int, help='Number of queries.') +parser.add_argument('COORD_MAX', type=int, nargs='?', default=10**9, help='Range of coord x.') +parser.add_argument('COORD_MAX', type=int, nargs='?', default=10**9, help='Range of coord y.') +parser.add_argument('MOD - 1', type=int, nargs='?', default=998244352, help='Range of initial weight.') +parser.add_argument('-OP', nargs='*', default=[0, 1, 2, 3], help='Type of operations.') + +args = parser.parse_args() + +N_MAX = args.N_MAX +Q_MAX = args.Q_MAX +COORD_MAX = args.COORD_MAX +COORD_MAX = args.COORD_MAX +MOD - 1 = args.MOD - 1 +OP = list(map(int, args.OP)) + +assert set(OP).issubset({0, 1, 2, 3}) + +n = rd.randint(1, N_MAX) +q = rd.randint(1, Q_MAX) + +print(n, q) + +size = n + +for _ in range(n): + print(rd.randint(0, COORD_MAX), rd.randint(0, COORD_MAX), rd.randint(0, MOD - 1)) + +for _ in range(q): + + op = rd.choice(OP) + + print(op, end=' ') + + if op == 0: + print(rd.randint(0, COORD_MAX), rd.randint(0, COORD_MAX), rd.randint(0, MOD - 1)) + size += 1 + + elif op == 1: + print(rd.randrange(0, size), rd.randint(0, MOD - 1)) + + else: + l = rd.randint(0, COORD_MAX) + r = rd.randint(0, COORD_MAX) + while l == r: + l = rd.randint(0, COORD_MAX) + r = rd.randint(0, COORD_MAX) + + d = rd.randint(0, COORD_MAX) + u = rd.randint(0, COORD_MAX) + while d == u: + d = rd.randint(0, COORD_MAX) + u = rd.randint(0, COORD_MAX) + + if l > r: + l, r = r, l + if d > u: + d, u = u, d + + if op == 2: + print(l, d, r, u) + else: + print(l, d, r, u, rd.randint(0, MOD - 1), rd.randint(0, MOD - 1)) \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_affine_queries.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_affine_queries.cpp new file mode 100644 index 00000000..170d438c --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_affine_queries.cpp @@ -0,0 +1,56 @@ +// Adapted from gen_random.py + +#include +#include +#include "random.h" +#include "../params.h" + +const int OP[] = {0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; + +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) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + } + + for (int i = 0; i < q; ++i) { + int op = OP[gen.uniform(0, sizeof(OP) / 4 - 1)]; + printf("%d ", op); + if (op == 0) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + ++n; + } + else if (op == 1) { + int idx = gen.uniform(0, n - 1); + int w = gen.uniform(0, MOD - 1); + printf("%d %d\n", idx, w); + } + else { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + + if (op == 2) { + printf("%d %d %d %d\n", l, d, r, u); + } + else { // op == 3 + int a = gen.uniform(0, MOD - 1); + int b = gen.uniform(0, MOD - 1); + printf("%d %d %d %d %d %d\n", l, d, r, u, a, b); + } + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_points.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_points.cpp new file mode 100644 index 00000000..74b19cb6 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_points.cpp @@ -0,0 +1,56 @@ +// Adapted from gen_random.py + +#include +#include +#include "random.h" +#include "../params.h" + +const int OP[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3}; + +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) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + } + + for (int i = 0; i < q; ++i) { + int op = OP[gen.uniform(0, sizeof(OP) / 4 - 1)]; + printf("%d ", op); + if (op == 0) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + ++n; + } + else if (op == 1) { + int idx = gen.uniform(0, n - 1); + int w = gen.uniform(0, MOD - 1); + printf("%d %d\n", idx, w); + } + else { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + + if (op == 2) { + printf("%d %d %d %d\n", l, d, r, u); + } + else { // op == 3 + int a = gen.uniform(0, MOD - 1); + int b = gen.uniform(0, MOD - 1); + printf("%d %d %d %d %d %d\n", l, d, r, u, a, b); + } + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_random_queries.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_random_queries.cpp new file mode 100644 index 00000000..9672362a --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_random_queries.cpp @@ -0,0 +1,56 @@ +// Adapted from gen_random.py + +#include +#include +#include "random.h" +#include "../params.h" + +const int OP[] = {0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3}; + +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) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + } + + for (int i = 0; i < q; ++i) { + int op = OP[gen.uniform(0, sizeof(OP) / 4 - 1)]; + printf("%d ", op); + if (op == 0) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + ++n; + } + else if (op == 1) { + int idx = gen.uniform(0, n - 1); + int w = gen.uniform(0, MOD - 1); + printf("%d %d\n", idx, w); + } + else { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + + if (op == 2) { + printf("%d %d %d %d\n", l, d, r, u); + } + else { // op == 3 + int a = gen.uniform(0, MOD - 1); + int b = gen.uniform(0, MOD - 1); + printf("%d %d %d %d %d %d\n", l, d, r, u, a, b); + } + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_sum_queries.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_sum_queries.cpp new file mode 100644 index 00000000..d90bcd15 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_sum_queries.cpp @@ -0,0 +1,56 @@ +// Adapted from gen_random.py + +#include +#include +#include "random.h" +#include "../params.h" + +const int OP[] = {0, 1, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + +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) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + } + + for (int i = 0; i < q; ++i) { + int op = OP[gen.uniform(0, sizeof(OP) / 4 - 1)]; + printf("%d ", op); + if (op == 0) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + ++n; + } + else if (op == 1) { + int idx = gen.uniform(0, n - 1); + int w = gen.uniform(0, MOD - 1); + printf("%d %d\n", idx, w); + } + else { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + + if (op == 2) { + printf("%d %d %d %d\n", l, d, r, u); + } + else { // op == 3 + int a = gen.uniform(0, MOD - 1); + int b = gen.uniform(0, MOD - 1); + printf("%d %d %d %d %d %d\n", l, d, r, u, a, b); + } + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_updates.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_updates.cpp new file mode 100644 index 00000000..32136866 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/many_updates.cpp @@ -0,0 +1,56 @@ +// Adapted from gen_random.py + +#include +#include +#include "random.h" +#include "../params.h" + +const int OP[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 3}; + +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) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + } + + for (int i = 0; i < q; ++i) { + int op = OP[gen.uniform(0, sizeof(OP) / 4 - 1)]; + printf("%d ", op); + if (op == 0) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + ++n; + } + else if (op == 1) { + int idx = gen.uniform(0, n - 1); + int w = gen.uniform(0, MOD - 1); + printf("%d %d\n", idx, w); + } + else { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + + if (op == 2) { + printf("%d %d %d %d\n", l, d, r, u); + } + else { // op == 3 + int a = gen.uniform(0, MOD - 1); + int b = gen.uniform(0, MOD - 1); + printf("%d %d %d %d %d %d\n", l, d, r, u, a, b); + } + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/max_random.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/max_random.cpp new file mode 100644 index 00000000..d4b9397a --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/max_random.cpp @@ -0,0 +1,56 @@ +// Adapted from gen_random.py + +#include +#include +#include "random.h" +#include "../params.h" + +const int OP[] = {0, 1, 2, 3}; + +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) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + } + + for (int i = 0; i < q; ++i) { + int op = OP[gen.uniform(0, sizeof(OP) / 4 - 1)]; + printf("%d ", op); + if (op == 0) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + ++n; + } + else if (op == 1) { + int idx = gen.uniform(0, n - 1); + int w = gen.uniform(0, MOD - 1); + printf("%d %d\n", idx, w); + } + else { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + + if (op == 2) { + printf("%d %d %d %d\n", l, d, r, u); + } + else { // op == 3 + int a = gen.uniform(0, MOD - 1); + int b = gen.uniform(0, MOD - 1); + printf("%d %d %d %d %d %d\n", l, d, r, u, a, b); + } + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/power_of_2.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/power_of_2.cpp new file mode 100644 index 00000000..56dd6fc1 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/power_of_2.cpp @@ -0,0 +1,59 @@ +// Adapted from gen_random.py + +#include +#include +#include "random.h" +#include "../params.h" + +const int OP[] = {0, 1, 2, 3, 0, 2, 3}; + +int main(int, char **argv) +{ + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = 1; + int q = 1; + while (n <= N_MAX) n *= 2; + while (q <= Q_MAX) q *= 2; + n >>= 1, q >>= 1; + printf("%d %d\n", n, q); + + for (int i = 0; i < n; ++i) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + } + + for (int i = 0; i < q; ++i) { + int op = OP[gen.uniform(0, sizeof(OP) / 4 - 1)]; + printf("%d ", op); + if (op == 0) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + ++n; + } + else if (op == 1) { + int idx = gen.uniform(0, n - 1); + int w = gen.uniform(0, MOD - 1); + printf("%d %d\n", idx, w); + } + else { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + + if (op == 2) { + printf("%d %d %d %d\n", l, d, r, u); + } + else { // op == 3 + int a = gen.uniform(0, MOD - 1); + int b = gen.uniform(0, MOD - 1); + printf("%d %d %d %d %d %d\n", l, d, r, u, a, b); + } + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/power_of_2_minus_1.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/power_of_2_minus_1.cpp new file mode 100644 index 00000000..f42b8549 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/power_of_2_minus_1.cpp @@ -0,0 +1,59 @@ +// Adapted from gen_random.py + +#include +#include +#include "random.h" +#include "../params.h" + +const int OP[] = {1, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3}; + +int main(int, char **argv) +{ + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = 1; + int q = 1; + while (n * 2 - 1 <= N_MAX) n *= 2; + while (q * 2 - 1 <= Q_MAX) q *= 2; + --n, --q; + printf("%d %d\n", n, q); + + for (int i = 0; i < n; ++i) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + } + + for (int i = 0; i < q; ++i) { + int op = OP[gen.uniform(0, sizeof(OP) / 4 - 1)]; + printf("%d ", op); + if (op == 0) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + ++n; + } + else if (op == 1) { + int idx = gen.uniform(0, n - 1); + int w = gen.uniform(0, MOD - 1); + printf("%d %d\n", idx, w); + } + else { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + + if (op == 2) { + printf("%d %d %d %d\n", l, d, r, u); + } + else { // op == 3 + int a = gen.uniform(0, MOD - 1); + int b = gen.uniform(0, MOD - 1); + printf("%d %d %d %d %d %d\n", l, d, r, u, a, b); + } + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/random.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/random.cpp new file mode 100644 index 00000000..0e1e3c93 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/random.cpp @@ -0,0 +1,56 @@ +// Adapted from gen_random.py + +#include +#include +#include "random.h" +#include "../params.h" + +const int OP[] = {0, 1, 2, 3}; + +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) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + } + + for (int i = 0; i < q; ++i) { + int op = OP[gen.uniform(0, sizeof(OP) / 4 - 1)]; + printf("%d ", op); + if (op == 0) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + ++n; + } + else if (op == 1) { + int idx = gen.uniform(0, n - 1); + int w = gen.uniform(0, MOD - 1); + printf("%d %d\n", idx, w); + } + else { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + + if (op == 2) { + printf("%d %d %d %d\n", l, d, r, u); + } + else { // op == 3 + int a = gen.uniform(0, MOD - 1); + int b = gen.uniform(0, MOD - 1); + printf("%d %d %d %d %d %d\n", l, d, r, u, a, b); + } + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/small.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/small.cpp new file mode 100644 index 00000000..1e26e4fd --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/small.cpp @@ -0,0 +1,56 @@ +// Adapted from gen_random.py + +#include +#include +#include "random.h" +#include "../params.h" + +const int OP[] = {0, 1, 2, 3}; + +int main(int, char **argv) +{ + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = gen.uniform(1, 1000); + int q = gen.uniform(1, 1000); + printf("%d %d\n", n, q); + + for (int i = 0; i < n; ++i) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + } + + for (int i = 0; i < q; ++i) { + int op = OP[gen.uniform(0, sizeof(OP) / 4 - 1)]; + printf("%d ", op); + if (op == 0) { + int x = gen.uniform(0, COORD_MAX); + int y = gen.uniform(0, COORD_MAX); + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + ++n; + } + else if (op == 1) { + int idx = gen.uniform(0, n - 1); + int w = gen.uniform(0, MOD - 1); + printf("%d %d\n", idx, w); + } + else { + auto [l, r] = gen.uniform_pair(0, COORD_MAX); + auto [d, u] = gen.uniform_pair(0, COORD_MAX); + + if (op == 2) { + printf("%d %d %d %d\n", l, d, r, u); + } + else { // op == 3 + int a = gen.uniform(0, MOD - 1); + int b = gen.uniform(0, MOD - 1); + printf("%d %d %d %d %d %d\n", l, d, r, u, a, b); + } + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/xy_concentrate.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/xy_concentrate.cpp new file mode 100644 index 00000000..43c92baf --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/gen/xy_concentrate.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include "random.h" +#include "../params.h" + +const int OP[] = {0, 1, 2, 3}; + +const int BLOCK = 1000; + +int main(int, char **argv) +{ + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + std::vector xs, ys; + for (int i = 0; i < BLOCK; i++) { + xs.emplace_back(gen.uniform(0, COORD_MAX - 1)); + ys.emplace_back(gen.uniform(0, COORD_MAX - 1)); + } + std::sort(xs.begin(), xs.end()); + std::sort(ys.begin(), ys.end()); + xs.emplace_back(COORD_MAX); + ys.emplace_back(COORD_MAX); + xs.erase(std::unique(xs.begin(), xs.end()), xs.end()); + ys.erase(std::unique(ys.begin(), ys.end()), ys.end()); + + int n = N_MAX; + int q = Q_MAX; + printf("%d %d\n", n, q); + + for (int i = 0; i < n; ++i) { + int x = xs[gen.uniform(0, xs.size() - 1)]; + int y = ys[gen.uniform(0, ys.size() - 1)]; + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + } + + for (int i = 0; i < q; ++i) { + int op = OP[gen.uniform(0, sizeof(OP) / 4 - 1)]; + printf("%d ", op); + if (op == 0) { + int x = xs[gen.uniform(0, xs.size() - 1)]; + int y = ys[gen.uniform(0, ys.size() - 1)]; + int w = gen.uniform(0, MOD - 1); + printf("%d %d %d\n", x, y, w); + ++n; + } + else if (op == 1) { + int idx = gen.uniform(0, n - 1); + int w = gen.uniform(0, MOD - 1); + printf("%d %d\n", idx, w); + } + else { + auto [l, r] = gen.uniform_pair(0, xs.size() - 1); + auto [d, u] = gen.uniform_pair(0, ys.size() - 1); + l = xs[l], r = xs[r]; + d = ys[d], u = ys[u]; + + if (op == 2) { + printf("%d %d %d %d\n", l, d, r, u); + } + else { // op == 3 + int a = gen.uniform(0, MOD - 1); + int b = gen.uniform(0, MOD - 1); + printf("%d %d %d %d %d %d\n", l, d, r, u, a, b); + } + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/hash.json b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/hash.json new file mode 100644 index 00000000..d1120383 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/hash.json @@ -0,0 +1,48 @@ +{ + "example_00.in": "866680913495582a2090afab34937971a978a229997a6c372fc3c01ab7f63d1a", + "example_00.out": "12ca11a48ef29b5c86b9ccb60c20de7a00acd50ced065258b7355f6fb6a96d64", + "many_affine_queries_00.in": "e2ad042b96ea2be8bd17755b018450a3217c7c4df3d9d3331059d7f76b990278", + "many_affine_queries_00.out": "b87c2fcc9e3dad1c809afb048d5633c6d7167fc6eee896ef45f7674ff4698052", + "many_points_00.in": "f24a64d3482eb21b35eb67a0a4f0a274ad8b3d15e49fd4d87bb6587e0858ee28", + "many_points_00.out": "9cedfbab8aa5f8c032e70686759c162f09879c84ff5ede3699623bca34b96026", + "many_random_queries_00.in": "7d59cf4dff3b2d6db906883df59ff7e6985cb28a32774033f08aac7f5b2100c2", + "many_random_queries_00.out": "295ad03dbf718ac498598c4c857699a4945f74fe9a5c64e08415851a6686c009", + "many_sum_queries_00.in": "856624a13082981ba7043ceab90065161bf9d8d8cc9c32125165f5a3cdd06c94", + "many_sum_queries_00.out": "0ff2e0ac62bc9279b1edc0f5ea90df6f6b7fff59ba78d630d92170244ce496d0", + "many_updates_00.in": "ae9e57672aada63f3380d954139fcb8342e46da0d183d14dd150410dfa06aab8", + "many_updates_00.out": "9a0008822e6a3f21ba491a5215c63d1633b4515498658c52326257b7a6d43ed1", + "max_random_00.in": "8be27fabfeaa3e8cdb4946ffc8d419a6f26a533fa7930864999253259274a033", + "max_random_00.out": "c01fd2bae133117b16203fe7f046d58a2495b2367c66ffc36ba9cfcd0cbdfd59", + "max_random_01.in": "254f981709e19fb3c2d282460c7ea4a16db0cab55b2d7f92aad7ebf4bcfa99dd", + "max_random_01.out": "1ae76efe3d9e18be33550d704a01e47b9e520357895bf0ef2a1600d6f245e2c4", + "power_of_2_00.in": "cde2b650a8fb67ae999d20d09042a792f4a7aef531c6e3cecac8bca4559e8006", + "power_of_2_00.out": "1ffa77ba91b7b84af8c0fdca0ccf981f437114b648f34a77a6ef187a4c653982", + "power_of_2_01.in": "063959399625f69d9532e32a59430791c580df0f11709af99c7580b60fdbbe77", + "power_of_2_01.out": "405199f778a7f1efd9cd6daa534842e4373ec1881a9d7f446e8c7058bd99f675", + "power_of_2_minus_1_00.in": "e25e10a3e79e362286d3a86b725e6378d8f9a2a616738da30dcbf4c98913421f", + "power_of_2_minus_1_00.out": "4163fa8bd771c5474504f7d346461a47ca04542c14cf6eb6cd12bda7ab85c8ab", + "power_of_2_minus_1_01.in": "989fac9ebfbd2f981e168b819080318934c39b0139d7a28cba95ea83c30a9879", + "power_of_2_minus_1_01.out": "cf5f9c9365986a0a12bb5d33333b8fa163bf7a9cfcde6552d134d39fe51fa668", + "random_00.in": "408e7a9983ddac2e91b5562dd534634f0fe4d8b273d512bb5a89a71b9d3278e2", + "random_00.out": "54bea4d50ea32106b302a0aa1772f89f6dce46a7e910866e66ca0b886f2f6a53", + "random_01.in": "7741b5d88edf9fd6828ef87919c425fe0b2ee177d30958da3797ab75247f84a4", + "random_01.out": "8ec5527cc438e0f5fb6e77c55aeb89130a39465e5ea3a56e5f4345e7d5371092", + "random_02.in": "1fbec827cd3197cb23ae5bbe565e5f64c6ac0522562675aaaa44580394048650", + "random_02.out": "ec578b10b05f4d45ecde24d708bce86817b4e200df449b089a4b71b842ffcecf", + "small_00.in": "014fb0a14f3ed839da2069abb6e3725e6831e4efbefc8140a71697b9a583abbc", + "small_00.out": "8ce8221b8a3496302fd53dc455f272296d67c9d5dbe8b8a53c36548b328c0995", + "small_01.in": "58749586ccffab952a6522c3e70af70a18724f5cbc76a01cb5627a8cf571fda9", + "small_01.out": "5d9197bbdce32e139f3b8d0f7b395e642445d36b9d953cf2245849b44aeda9d4", + "small_02.in": "1057bf0cda826648922893a41d8a4dd28d64cefb0e332832cd27b889dc3e30dc", + "small_02.out": "a23d5b4d7f876e48f8b8d32c884c42205ace4bf78a8300833618ac79b9cc7109", + "small_03.in": "3c7ae964cf86b161d9756ad12d1ca42b55e299971aa680c0925a8fcadfaff3fc", + "small_03.out": "167d33fc25b1c934b6cec91539c3cd8623f5972e8b1eeea6e5b1bba765606d51", + "small_04.in": "02566c54c0ae4968002e6c077c1b65267a623e2ceb55c8acf108495a14b92275", + "small_04.out": "6847129ab4181c7d9cd2d3bdd2e0d5e1f9cdef078e1b68a66d5efaf0dfb2b509", + "xy_concentrate_00.in": "a12226f4cfbdd0a100e7f8e5b74b036cf9ea50b1522302676d201a46ea3680e3", + "xy_concentrate_00.out": "e65ea5fa1963e266cd28a474450b0a1da95917ed72c51d95128a83703ac98107", + "xy_concentrate_01.in": "66af4c8feccec662d1ceb030523ed1f6ca3d4fdd9c02c688ec83ebbfa7acc50d", + "xy_concentrate_01.out": "0fcf806e80f4dea75cf5454cbb37a953a58c8b53efbed54a3287ada5adcd013a", + "xy_concentrate_02.in": "006fded5840499b5fce1214192d5401c4cb5f185c7a3ed35e19184e37cf1308e", + "xy_concentrate_02.out": "55b88494da2ab853a90a07bf47a27abed516e39f7569af120add5a0149646f6c" +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/info.toml b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/info.toml new file mode 100644 index 00000000..435298e0 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/info.toml @@ -0,0 +1,53 @@ +title = 'Dynamic Point Rectangle Affine Rectangle Sum' +timelimit = 10.0 +forum = "https://github.com/yosupo06/library-checker-problems/issues/1279" + +[[tests]] + name = "example.in" + number = 1 +[[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_updates.cpp" + number = 1 +[[tests]] + name = "many_random_queries.cpp" + number = 1 +[[tests]] + name = "many_sum_queries.cpp" + number = 1 +[[tests]] + name = "many_affine_queries.cpp" + number = 1 +[[tests]] + name = "xy_concentrate.cpp" + number = 3 +[[tests]] + name = "power_of_2.cpp" + number = 2 +[[tests]] + name = "power_of_2_minus_1.cpp" + number = 2 + +[params] + N_MAX = 100_000 + Q_MAX = 100_000 + COORD_MAX = 1000_000_000 + MOD = 998_244_353 + +[[solutions]] + name = "online.cpp" + +[[solutions]] + name = "brute_force.cpp" + allow_tle = true \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/sol/brute_force.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/sol/brute_force.cpp new file mode 100644 index 00000000..f6ba1414 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/sol/brute_force.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include "modint.hpp" +using namespace std; + +using i32 = int; +using i64 = long long; +using u32 = unsigned int; +using u64 = unsigned long long; + +template using vec = vector; + +signed main() +{ + // ios::sync_with_stdio(false); + // cin.tie(0), cout.tie(0); + u32 n, q; + // cin >> n >> q; + scanf("%u %u", &n, &q); + using mint = atcoder::modint998244353; + using Point = pair, mint>; + + vec t(n); + for (auto &[p, w]: t) { + // cin >> p.first >> p.second >> n; + scanf("%u %u %u", &p.first, &p.second, &n); + w = n; + } + u32 op, a, b, c, d, e, f; + while (q--) { + // cin >> op; + scanf("%u", &op); + if (op == 0) { + // cin >> a >> b >> c; + scanf("%u %u %u", &a, &b, &c); + t.emplace_back(make_pair(a, b), c); + } + else if (op == 1) { + // cin >> a >> b; + scanf("%u %u", &a, &b); + t[a].second = b; + } + else if (op == 2) { + // cin >> a >> b >> c >> d; + scanf("%u %u %u %u", &a, &b, &c, &d); + mint res = 0; + for (auto [p, w]: t) { + auto [x, y] = p; + if (a <= x && x < c && b <= y && y < d) { + res += w; + } + } + // cout << res.val() << '\n'; + printf("%u\n", res.val()); + } + else { + // cin >> a >> b >> c >> d >> e >> f; + scanf("%u %u %u %u %u %u", &a, &b, &c, &d, &e, &f); + for (auto &[p, w]: t) { + auto [x, y] = p; + if (a <= x && x < c && b <= y && y < d) { + w = e * w + f; + } + } + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/sol/correct.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/sol/correct.cpp new file mode 100644 index 00000000..f45f65fa --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/sol/correct.cpp @@ -0,0 +1,266 @@ +// Offline solution + +#include +#include +#include +#include +#include +#include "modint.hpp" +using namespace std; + +using i32 = int; +using i64 = long long; +using u32 = unsigned int; +using u64 = unsigned long long; + +template using vec = vector; + +template::value> +struct LazyKDTree +{ + +#define KDT_MIS make_index_sequence{} +#define KDT_ARGS const PT& a, const PT& b, index_sequence + + template + PT min_pt(KDT_ARGS) {return { min(std::get(a), std::get(b))... };} + template + PT max_pt(KDT_ARGS) {return { max(std::get(a), std::get(b))... };} + + template + bool cle_pt_impl(KDT_ARGS) + { return ((std::get(a) <= std::get(b)) && ...); } + bool cle_pt(const PT& a, const PT& b){ return cle_pt_impl(a, b, KDT_MIS); } + + using MS = typename M::MS; + using MA = typename M::MA; + using S = typename MS::S; + using A = typename MA::S; + + struct Node + { + // Vector sp -> ep describes the hypercube. + PT sp, ep; + S val; + Node(const PT &_sp, const PT &_tp, const S &s = M::un()): + sp(_sp), ep(_tp), val(s) { } + Node() { } + }; + + u32 n; + vec t; + vec d; + vec rnk; + + LazyKDTree(): n() { } + LazyKDTree(u32 _n, const vec &p, const vec &s) + : n(_n), t(), d(), rnk(n) + { + u32 m = 1; + while (m < n) m += m; + t.resize(m, MA::un()); + d.resize(m * 2); + vec idx(n); + for (u32 i = 0; i < n; i++) idx[i] = i; + build_rec<0>(p, s, idx, 0, n, 1); + } + + void apply_at(u32 x, const A& a, u32 len) + { + d[x].val = M::act(d[x].val, a, len); + if (len > 1) t[x] = MA::op(t[x], a); + } + void push_down(u32 x, u32 l, u32 r) + { + if (t[x] == MA::un()) return ; + apply_at(x * 2, t[x], l); + apply_at(x * 2 + 1, t[x], r); + t[x] = MA::un(); + } + + // Vector st -> ed describes a hypercube. + S prod(const PT &st, const PT &ed) { return prod_rec(st, ed, 0, n, 1); } + S get(u32 x) { return get_rec(x, 0, n, 1); } + void set(u32 x, const S &v) { set_rec(rnk[x], v, 0, n, 1); } + void apply(const PT &st, const PT &ed, const A &a) + { + apply_rec(st, ed, a, 0, n, 1); + } + template + void print_val(RIt o) + { + vec idx(n); + for (u32 i = 0; i < n; i++) idx[rnk[i]] = i; + print_rec(idx, 0, n, 1, o); + } + + template + void build_rec(const vec &p, const vec &s, + vec &idx, u32 l, u32 r, u32 x) + { + if (l + 1 == r) { + u32 idn = idx[l]; + d[x] = {p[idn], p[idn], s[idn]}; + rnk[idn] = l; + return ; + } + u32 mid = (l + r) >> 1; + nth_element(idx.data() + l, idx.data() + mid, idx.data() + r, + [&p](u32 a, u32 b) + { return std::get(p[a]) < std::get(p[b]); }); + build_rec<(D + 1) % K>(p, s, idx, l, mid, x * 2); + build_rec<(D + 1) % K>(p, s, idx, mid, r, x * 2 + 1); + d[x].sp = min_pt(d[x * 2].sp, d[x * 2 + 1].sp, KDT_MIS); + d[x].ep = max_pt(d[x * 2].ep, d[x * 2 + 1].ep, KDT_MIS); + d[x].val = MS::op(d[x * 2].val, d[x * 2 + 1].val); + } + +private: + + S prod_rec(const PT &st, const PT &ed, u32 l, u32 r, u32 x) + { + if (cle_pt(st, d[x].sp) && cle_pt(d[x].ep, ed)) return d[x].val; + if (!cle_pt(d[x].sp, ed) || !cle_pt(st, d[x].ep)) return MS::un(); + u32 mid = (l + r) >> 1; + push_down(x, mid - l, r - mid); + return MS::op(prod_rec(st, ed, l, mid, x * 2), + prod_rec(st, ed, mid, r, x * 2 + 1)); + } + + void apply_rec(const PT &st, const PT &ed, const A &a, u32 l, u32 r, u32 x) + { + if (cle_pt(st, d[x].sp) && cle_pt(d[x].ep, ed)) { + apply_at(x, a, r - l); + return ; + } + if (!cle_pt(d[x].sp, ed) || !cle_pt(st, d[x].ep)) return ; + u32 mid = (l + r) >> 1; + push_down(x, mid - l, r - mid); + apply_rec(st, ed, a, l, mid, x * 2); + apply_rec(st, ed, a, mid, r, x * 2 + 1); + d[x].val = MS::op(d[x * 2].val, d[x * 2 + 1].val); + } + + void set_rec(u32 p, const S &v, u32 l, u32 r, u32 x) + { + if (l + 1 == r) { + d[x].val = v; + return ; + } + u32 mid = (l + r) >> 1; + push_down(x, mid - l, r - mid); + if (p < mid) set_rec(p, v, l, mid, x * 2); + else set_rec(p, v, mid, r, x * 2 + 1); + d[x].val = MS::op(d[x * 2].val, d[x * 2 + 1].val); + } + + S get_rec(u32 p, u32 l, u32 r, u32 x) + { + if (l + 1 == r) return d[x].val; + u32 mid = (l + r) >> 1; + push_down(x, mid - l, r - mid); + if (p < mid) return get_rec(p, l, mid, x * 2); + return get_rec(p, mid, r, x * 2 + 1); + } + + template + void print_rec(const vec &idx, u32 l, u32 r, u32 x, RIt o) + { + if (l + 1 == r) { + o[idx[l]] = d[x].val; + return ; + } + u32 mid = (l + r) >> 1; + push_down(x, mid - l, r - mid); + print_rec(idx, l, mid, x * 2, o); + print_rec(idx, mid, r, x * 2 + 1, o); + } + +#undef KDT_MIS +#undef KDT_ARGS +}; + +using mint = atcoder::modint998244353; + +struct MonoidSum +{ + using S = pair; + static S op(S a, S b) { return {a.first + b.first, a.second + b.second}; } + static S un() { return S(); } +}; +struct MonoidAffine +{ + using S = pair; + static S op(const S &a, const S &b) + { + return {a.first * b.first, a.second * b.first + b.second}; + } + static S un() { return {1, 0}; } +}; +struct ActedMonoid +{ + using MS = MonoidSum; + using MA = MonoidAffine; + static pair + act(const pair v, const pair &a, u32) + { + return {v.first * a.first + v.second * a.second, v.second}; + } +}; + +struct Query +{ + u32 op, a, b, c, d, e, f; +}; + +signed main() +{ + // ios::sync_with_stdio(false); + // cin.tie(0), cout.tie(0); + using Point = pair; + u32 n, q; + // cin >> n >> q; + scanf("%u %u", &n, &q); + vec pt; + vec> v; + vec qr(q); + for (u32 i = 0, x, y, z; i < n; i++) { + // cin >> x >> y >> z; + scanf("%u %u %u", &x, &y, &z); + pt.emplace_back(x, y); + v.emplace_back(z, 1); + } + for (auto &[op, a, b, c, d, e, f]: qr) { + // cin >> op; + scanf("%u", &op); + if (op == 0) { + // cin >> a >> b >> c; + scanf("%u %u %u", &a, &b, &c); + pt.emplace_back(a, b); + v.emplace_back(0, 0); + a = pt.size() - 1, b = c; + } + else if (op == 1) { + // cin >> a >> b; + scanf("%u %u", &a, &b); + } + else if (op == 2) { + // cin >> a >> b >> c >> d; + scanf("%u %u %u %u", &a, &b, &c, &d); + } + else { + // cin >> a >> b >> c >> d >> e >> f; + scanf("%u %u %u %u %u %u", &a, &b, &c, &d, &e, &f); + } + } + LazyKDTree t(pt.size(), pt, v); + for (auto [op, a, b, c, d, e, f]: qr) { + if (op <= 1) t.set(a, {b, 1}); + else if (op == 2) { + // cout << t.prod({a, b}, {c - 1, d - 1}).first.val() << '\n'; + printf("%u\n", t.prod({a, b}, {c - 1, d - 1}).first.val()); + } + else t.apply({a, b}, {c - 1, d - 1}, {e, f}); + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/sol/modint.hpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/sol/modint.hpp new file mode 100644 index 00000000..95a0a88e --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/sol/modint.hpp @@ -0,0 +1,586 @@ +#ifndef ATCODER_MODINT_HPP +#define ATCODER_MODINT_HPP 1 + +#include +#include +#include + +#ifdef _MSC_VER +#include +#endif + +#ifndef ATCODER_INTERNAL_MATH_HPP +#define ATCODER_INTERNAL_MATH_HPP 1 + +#include + +#ifdef _MSC_VER +#include +#endif + +namespace atcoder { + +namespace internal { + +// @param m `1 <= m` +// @return x mod m +constexpr long long safe_mod(long long x, long long m) { + x %= m; + if (x < 0) x += m; + return x; +} + +// Fast modular multiplication by barrett reduction +// Reference: https://en.wikipedia.org/wiki/Barrett_reduction +// NOTE: reconsider after Ice Lake +struct barrett { + unsigned int _m; + unsigned long long im; + + // @param m `1 <= m` + explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {} + + // @return m + unsigned int umod() const { return _m; } + + // @param a `0 <= a < m` + // @param b `0 <= b < m` + // @return `a * b % m` + unsigned int mul(unsigned int a, unsigned int b) const { + // [1] m = 1 + // a = b = im = 0, so okay + + // [2] m >= 2 + // im = ceil(2^64 / m) + // -> im * m = 2^64 + r (0 <= r < m) + // let z = a*b = c*m + d (0 <= c, d < m) + // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im + // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2 + // ((ab * im) >> 64) == c or c + 1 + unsigned long long z = a; + z *= b; +#ifdef _MSC_VER + unsigned long long x; + _umul128(z, im, &x); +#else + unsigned long long x = + (unsigned long long)(((unsigned __int128)(z)*im) >> 64); +#endif + unsigned long long y = x * _m; + return (unsigned int)(z - y + (z < y ? _m : 0)); + } +}; + +// @param n `0 <= n` +// @param m `1 <= m` +// @return `(x ** n) % m` +constexpr long long pow_mod_constexpr(long long x, long long n, int m) { + if (m == 1) return 0; + unsigned int _m = (unsigned int)(m); + unsigned long long r = 1; + unsigned long long y = safe_mod(x, m); + while (n) { + if (n & 1) r = (r * y) % _m; + y = (y * y) % _m; + n >>= 1; + } + return r; +} + +// Reference: +// M. Forisek and J. Jancina, +// Fast Primality Testing for Integers That Fit into a Machine Word +// @param n `0 <= n` +constexpr bool is_prime_constexpr(int n) { + if (n <= 1) return false; + if (n == 2 || n == 7 || n == 61) return true; + if (n % 2 == 0) return false; + long long d = n - 1; + while (d % 2 == 0) d /= 2; + constexpr long long bases[3] = {2, 7, 61}; + for (long long a : bases) { + long long t = d; + long long y = pow_mod_constexpr(a, t, n); + while (t != n - 1 && y != 1 && y != n - 1) { + y = y * y % n; + t <<= 1; + } + if (y != n - 1 && t % 2 == 0) { + return false; + } + } + return true; +} +template constexpr bool is_prime = is_prime_constexpr(n); + +// @param b `1 <= b` +// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g +constexpr std::pair inv_gcd(long long a, long long b) { + a = safe_mod(a, b); + if (a == 0) return {b, 0}; + + // Contracts: + // [1] s - m0 * a = 0 (mod b) + // [2] t - m1 * a = 0 (mod b) + // [3] s * |m1| + t * |m0| <= b + long long s = b, t = a; + long long m0 = 0, m1 = 1; + + while (t) { + long long u = s / t; + s -= t * u; + m0 -= m1 * u; // |m1 * u| <= |m1| * s <= b + + // [3]: + // (s - t * u) * |m1| + t * |m0 - m1 * u| + // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u) + // = s * |m1| + t * |m0| <= b + + auto tmp = s; + s = t; + t = tmp; + tmp = m0; + m0 = m1; + m1 = tmp; + } + // by [3]: |m0| <= b/g + // by g != b: |m0| < b/g + if (m0 < 0) m0 += b / s; + return {s, m0}; +} + +// Compile time primitive root +// @param m must be prime +// @return primitive root (and minimum in now) +constexpr int primitive_root_constexpr(int m) { + if (m == 2) return 1; + if (m == 167772161) return 3; + if (m == 469762049) return 3; + if (m == 754974721) return 11; + if (m == 998244353) return 3; + int divs[20] = {}; + divs[0] = 2; + int cnt = 1; + int x = (m - 1) / 2; + while (x % 2 == 0) x /= 2; + for (int i = 3; (long long)(i)*i <= x; i += 2) { + if (x % i == 0) { + divs[cnt++] = i; + while (x % i == 0) { + x /= i; + } + } + } + if (x > 1) { + divs[cnt++] = x; + } + for (int g = 2;; g++) { + bool ok = true; + for (int i = 0; i < cnt; i++) { + if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) { + ok = false; + break; + } + } + if (ok) return g; + } +} +template constexpr int primitive_root = primitive_root_constexpr(m); + +// @param n `n < 2^32` +// @param m `1 <= m < 2^32` +// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64) +unsigned long long floor_sum_unsigned(unsigned long long n, + unsigned long long m, + unsigned long long a, + unsigned long long b) { + unsigned long long ans = 0; + while (true) { + if (a >= m) { + ans += n * (n - 1) / 2 * (a / m); + a %= m; + } + if (b >= m) { + ans += n * (b / m); + b %= m; + } + + unsigned long long y_max = a * n + b; + if (y_max < m) break; + // y_max < m * (n + 1) + // floor(y_max / m) <= n + n = (unsigned long long)(y_max / m); + b = (unsigned long long)(y_max % m); + std::swap(m, a); + } + return ans; +} + +} // namespace internal + +} // namespace atcoder + +#endif // ATCODER_INTERNAL_MATH_HPP + +#ifndef ATCODER_INTERNAL_TYPE_TRAITS_HPP +#define ATCODER_INTERNAL_TYPE_TRAITS_HPP 1 + +#include +#include +#include + +namespace atcoder { + +namespace internal { + +#ifndef _MSC_VER +template +using is_signed_int128 = + typename std::conditional::value || + std::is_same::value, + std::true_type, + std::false_type>::type; + +template +using is_unsigned_int128 = + typename std::conditional::value || + std::is_same::value, + std::true_type, + std::false_type>::type; + +template +using make_unsigned_int128 = + typename std::conditional::value, + __uint128_t, + unsigned __int128>; + +template +using is_integral = typename std::conditional::value || + is_signed_int128::value || + is_unsigned_int128::value, + std::true_type, + std::false_type>::type; + +template +using is_signed_int = typename std::conditional<(is_integral::value && + std::is_signed::value) || + is_signed_int128::value, + std::true_type, + std::false_type>::type; + +template +using is_unsigned_int = + typename std::conditional<(is_integral::value && + std::is_unsigned::value) || + is_unsigned_int128::value, + std::true_type, + std::false_type>::type; + +template +using to_unsigned = typename std::conditional< + is_signed_int128::value, + make_unsigned_int128, + typename std::conditional::value, + std::make_unsigned, + std::common_type>::type>::type; + +#else + +template using is_integral = typename std::is_integral; + +template +using is_signed_int = + typename std::conditional::value && std::is_signed::value, + std::true_type, + std::false_type>::type; + +template +using is_unsigned_int = + typename std::conditional::value && + std::is_unsigned::value, + std::true_type, + std::false_type>::type; + +template +using to_unsigned = typename std::conditional::value, + std::make_unsigned, + std::common_type>::type; + +#endif + +template +using is_signed_int_t = std::enable_if_t::value>; + +template +using is_unsigned_int_t = std::enable_if_t::value>; + +template using to_unsigned_t = typename to_unsigned::type; + +} // namespace internal + +} // namespace atcoder + +#endif // ATCODER_INTERNAL_TYPE_TRAITS_HPP + + +namespace atcoder { + +namespace internal { + +struct modint_base {}; +struct static_modint_base : modint_base {}; + +template using is_modint = std::is_base_of; +template using is_modint_t = std::enable_if_t::value>; + +} // namespace internal + +template * = nullptr> +struct static_modint : internal::static_modint_base { + using mint = static_modint; + + public: + static constexpr int mod() { return m; } + static mint raw(int v) { + mint x; + x._v = v; + return x; + } + + static_modint() : _v(0) {} + template * = nullptr> + static_modint(T v) { + long long x = (long long)(v % (long long)(umod())); + if (x < 0) x += umod(); + _v = (unsigned int)(x); + } + template * = nullptr> + static_modint(T v) { + _v = (unsigned int)(v % umod()); + } + + unsigned int val() const { return _v; } + + mint& operator++() { + _v++; + if (_v == umod()) _v = 0; + return *this; + } + mint& operator--() { + if (_v == 0) _v = umod(); + _v--; + return *this; + } + mint operator++(int) { + mint result = *this; + ++*this; + return result; + } + mint operator--(int) { + mint result = *this; + --*this; + return result; + } + + mint& operator+=(const mint& rhs) { + _v += rhs._v; + if (_v >= umod()) _v -= umod(); + return *this; + } + mint& operator-=(const mint& rhs) { + _v -= rhs._v; + if (_v >= umod()) _v += umod(); + return *this; + } + mint& operator*=(const mint& rhs) { + unsigned long long z = _v; + z *= rhs._v; + _v = (unsigned int)(z % umod()); + return *this; + } + mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); } + + mint operator+() const { return *this; } + mint operator-() const { return mint() - *this; } + + mint pow(long long n) const { + assert(0 <= n); + mint x = *this, r = 1; + while (n) { + if (n & 1) r *= x; + x *= x; + n >>= 1; + } + return r; + } + mint inv() const { + if (prime) { + assert(_v); + return pow(umod() - 2); + } else { + auto eg = internal::inv_gcd(_v, m); + assert(eg.first == 1); + return eg.second; + } + } + + friend mint operator+(const mint& lhs, const mint& rhs) { + return mint(lhs) += rhs; + } + friend mint operator-(const mint& lhs, const mint& rhs) { + return mint(lhs) -= rhs; + } + friend mint operator*(const mint& lhs, const mint& rhs) { + return mint(lhs) *= rhs; + } + friend mint operator/(const mint& lhs, const mint& rhs) { + return mint(lhs) /= rhs; + } + friend bool operator==(const mint& lhs, const mint& rhs) { + return lhs._v == rhs._v; + } + friend bool operator!=(const mint& lhs, const mint& rhs) { + return lhs._v != rhs._v; + } + + private: + unsigned int _v; + static constexpr unsigned int umod() { return m; } + static constexpr bool prime = internal::is_prime; +}; + +template struct dynamic_modint : internal::modint_base { + using mint = dynamic_modint; + + public: + static int mod() { return (int)(bt.umod()); } + static void set_mod(int m) { + assert(1 <= m); + bt = internal::barrett(m); + } + static mint raw(int v) { + mint x; + x._v = v; + return x; + } + + dynamic_modint() : _v(0) {} + template * = nullptr> + dynamic_modint(T v) { + long long x = (long long)(v % (long long)(mod())); + if (x < 0) x += mod(); + _v = (unsigned int)(x); + } + template * = nullptr> + dynamic_modint(T v) { + _v = (unsigned int)(v % mod()); + } + + unsigned int val() const { return _v; } + + mint& operator++() { + _v++; + if (_v == umod()) _v = 0; + return *this; + } + mint& operator--() { + if (_v == 0) _v = umod(); + _v--; + return *this; + } + mint operator++(int) { + mint result = *this; + ++*this; + return result; + } + mint operator--(int) { + mint result = *this; + --*this; + return result; + } + + mint& operator+=(const mint& rhs) { + _v += rhs._v; + if (_v >= umod()) _v -= umod(); + return *this; + } + mint& operator-=(const mint& rhs) { + _v += mod() - rhs._v; + if (_v >= umod()) _v -= umod(); + return *this; + } + mint& operator*=(const mint& rhs) { + _v = bt.mul(_v, rhs._v); + return *this; + } + mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); } + + mint operator+() const { return *this; } + mint operator-() const { return mint() - *this; } + + mint pow(long long n) const { + assert(0 <= n); + mint x = *this, r = 1; + while (n) { + if (n & 1) r *= x; + x *= x; + n >>= 1; + } + return r; + } + mint inv() const { + auto eg = internal::inv_gcd(_v, mod()); + assert(eg.first == 1); + return eg.second; + } + + friend mint operator+(const mint& lhs, const mint& rhs) { + return mint(lhs) += rhs; + } + friend mint operator-(const mint& lhs, const mint& rhs) { + return mint(lhs) -= rhs; + } + friend mint operator*(const mint& lhs, const mint& rhs) { + return mint(lhs) *= rhs; + } + friend mint operator/(const mint& lhs, const mint& rhs) { + return mint(lhs) /= rhs; + } + friend bool operator==(const mint& lhs, const mint& rhs) { + return lhs._v == rhs._v; + } + friend bool operator!=(const mint& lhs, const mint& rhs) { + return lhs._v != rhs._v; + } + + private: + unsigned int _v; + static internal::barrett bt; + static unsigned int umod() { return bt.umod(); } +}; +template internal::barrett dynamic_modint::bt(998244353); + +using modint998244353 = static_modint<998244353>; +using modint1000000007 = static_modint<1000000007>; +using modint = dynamic_modint<-1>; + +namespace internal { + +template +using is_static_modint = std::is_base_of; + +template +using is_static_modint_t = std::enable_if_t::value>; + +template struct is_dynamic_modint : public std::false_type {}; +template +struct is_dynamic_modint> : public std::true_type {}; + +template +using is_dynamic_modint_t = std::enable_if_t::value>; + +} // namespace internal + +} // namespace atcoder + +#endif // ATCODER_MODINT_HPP diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/sol/online.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/sol/online.cpp new file mode 100644 index 00000000..305647de --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/sol/online.cpp @@ -0,0 +1,323 @@ +#include +#include +#include +#include +#include +#include "modint.hpp" +using namespace std; + +using i32 = int; +using i64 = long long; +using u32 = unsigned int; +using u64 = unsigned long long; + +template using vec = vector; + +template::value> +struct LazyKDTree +{ + +#define KDT_MIS make_index_sequence{} +#define KDT_ARGS const PT& a, const PT& b, index_sequence + + template + PT min_pt(KDT_ARGS) {return { min(std::get(a), std::get(b))... };} + template + PT max_pt(KDT_ARGS) {return { max(std::get(a), std::get(b))... };} + + template + bool cle_pt_impl(KDT_ARGS) + { return ((std::get(a) <= std::get(b)) && ...); } + bool cle_pt(const PT& a, const PT& b){ return cle_pt_impl(a, b, KDT_MIS); } + + using MS = typename M::MS; + using MA = typename M::MA; + using S = typename MS::S; + using A = typename MA::S; + + struct Node + { + // Vector sp -> ep describes the hypercube. + PT sp, ep; + S val; + Node(const PT &_sp, const PT &_tp, const S &s = M::un()): + sp(_sp), ep(_tp), val(s) { } + Node() { } + }; + + u32 n; + vec t; + vec d; + vec rnk; + + LazyKDTree(): n() { } + LazyKDTree(u32 _n, const vec &p, const vec &s) + : n(_n), t(), d(), rnk(n) + { + u32 m = 1; + while (m < n) m += m; + t.resize(m, MA::un()); + d.resize(m * 2); + vec idx(n); + for (u32 i = 0; i < n; i++) idx[i] = i; + build_rec<0>(p, s, idx, 0, n, 1); + } + + void apply_at(u32 x, const A& a, u32 len) + { + d[x].val = M::act(d[x].val, a, len); + if (len > 1) t[x] = MA::op(t[x], a); + } + void push_down(u32 x, u32 l, u32 r) + { + if (t[x] == MA::un()) return ; + apply_at(x * 2, t[x], l); + apply_at(x * 2 + 1, t[x], r); + t[x] = MA::un(); + } + + // Vector st -> ed describes a hypercube. + S prod(const PT &st, const PT &ed) { return prod_rec(st, ed, 0, n, 1); } + S get(u32 x) { return get_rec(x, 0, n, 1); } + void set(u32 x, const S &v) { set_rec(rnk[x], v, 0, n, 1); } + void apply(const PT &st, const PT &ed, const A &a) + { + apply_rec(st, ed, a, 0, n, 1); + } + template + void print_val(RIt o) + { + vec idx(n); + for (u32 i = 0; i < n; i++) idx[rnk[i]] = i; + print_rec(idx, 0, n, 1, o); + } + + template + void build_rec(const vec &p, const vec &s, + vec &idx, u32 l, u32 r, u32 x) + { + if (l + 1 == r) { + u32 idn = idx[l]; + d[x] = {p[idn], p[idn], s[idn]}; + rnk[idn] = l; + return ; + } + u32 mid = (l + r) >> 1; + nth_element(idx.data() + l, idx.data() + mid, idx.data() + r, + [&p](u32 a, u32 b) + { return std::get(p[a]) < std::get(p[b]); }); + build_rec<(D + 1) % K>(p, s, idx, l, mid, x * 2); + build_rec<(D + 1) % K>(p, s, idx, mid, r, x * 2 + 1); + d[x].sp = min_pt(d[x * 2].sp, d[x * 2 + 1].sp, KDT_MIS); + d[x].ep = max_pt(d[x * 2].ep, d[x * 2 + 1].ep, KDT_MIS); + d[x].val = MS::op(d[x * 2].val, d[x * 2 + 1].val); + } + +private: + + S prod_rec(const PT &st, const PT &ed, u32 l, u32 r, u32 x) + { + if (cle_pt(st, d[x].sp) && cle_pt(d[x].ep, ed)) return d[x].val; + if (!cle_pt(d[x].sp, ed) || !cle_pt(st, d[x].ep)) return MS::un(); + u32 mid = (l + r) >> 1; + push_down(x, mid - l, r - mid); + return MS::op(prod_rec(st, ed, l, mid, x * 2), + prod_rec(st, ed, mid, r, x * 2 + 1)); + } + + void apply_rec(const PT &st, const PT &ed, const A &a, u32 l, u32 r, u32 x) + { + if (cle_pt(st, d[x].sp) && cle_pt(d[x].ep, ed)) { + apply_at(x, a, r - l); + return ; + } + if (!cle_pt(d[x].sp, ed) || !cle_pt(st, d[x].ep)) return ; + u32 mid = (l + r) >> 1; + push_down(x, mid - l, r - mid); + apply_rec(st, ed, a, l, mid, x * 2); + apply_rec(st, ed, a, mid, r, x * 2 + 1); + d[x].val = MS::op(d[x * 2].val, d[x * 2 + 1].val); + } + + void set_rec(u32 p, const S &v, u32 l, u32 r, u32 x) + { + if (l + 1 == r) { + d[x].val = v; + return ; + } + u32 mid = (l + r) >> 1; + push_down(x, mid - l, r - mid); + if (p < mid) set_rec(p, v, l, mid, x * 2); + else set_rec(p, v, mid, r, x * 2 + 1); + d[x].val = MS::op(d[x * 2].val, d[x * 2 + 1].val); + } + + S get_rec(u32 p, u32 l, u32 r, u32 x) + { + if (l + 1 == r) return d[x].val; + u32 mid = (l + r) >> 1; + push_down(x, mid - l, r - mid); + if (p < mid) return get_rec(p, l, mid, x * 2); + return get_rec(p, mid, r, x * 2 + 1); + } + + template + void print_rec(const vec &idx, u32 l, u32 r, u32 x, RIt o) + { + if (l + 1 == r) { + o[idx[l]] = d[x].val; + return ; + } + u32 mid = (l + r) >> 1; + push_down(x, mid - l, r - mid); + print_rec(idx, l, mid, x * 2, o); + print_rec(idx, mid, r, x * 2 + 1, o); + } + +#undef KDT_MIS +#undef KDT_ARGS +}; + +template::value> +struct LazyKDForest +{ + using S = typename M::MS::S; + using A = typename M::MA::S; + using KDT = LazyKDTree; + + vec f; + + LazyKDForest(): f() { } + + void push_back(const PT &v, const S &w) + { + u32 ns = 1; + vec p(1, v); + vec s(1, w); + while (!f.empty() && f.back().n == ns) { + p.resize(ns * 2), s.resize(ns * 2); + auto &nw = f.back(); + for (u32 i = 1, len = ns; i < ns; i++) { + if ((i & -i) == i) len >>= 1; + nw.push_down(i, len, len); + } + for (u32 i = 0; i < ns; i++) { + auto &d = nw.d[nw.rnk[i] + ns]; + p[ns * 2 - i - 1] = d.sp; + s[ns * 2 - i - 1] = d.val; + } + ns *= 2; + f.pop_back(); + } + reverse(p.begin(), p.end()); + reverse(s.begin(), s.end()); + f.emplace_back(ns, p, s); + } + + S prod(const PT &st, const PT &ed) + { + S res = M::MS::un(); + for (auto &d: f) { + res = M::MS::op(res, d.prod(st, ed)); + } + return res; + } + + void set(u32 x, const S &s) + { + for (auto &d: f) { + if (x < d.n) { + d.set(x, s); + break; + } + x -= d.n; + } + } + + S get(u32 x) + { + for (auto &d: f) { + if (x < d.n) return d.get(x); + x -= d.n; + } + return M::MS::un(); + } + + void apply(const PT &st, const PT &ed, const A& a) + { + for (auto &d: f) d.apply(st, ed, a); + } +}; + +using mint = atcoder::modint998244353; + +struct MonoidSum +{ + using S = mint; + static S op(S a, S b) { return a + b; } + static S un() { return S(); } +}; +struct MonoidAffine +{ + using S = pair; + static S op(const S &a, const S &b) + { + return {a.first * b.first, a.second * b.first + b.second}; + } + static S un() { return {1, 0}; } +}; +struct ActedMonoid +{ + using MS = MonoidSum; + using MA = MonoidAffine; + static mint act(mint v, const pair &a, u32 len) + { + return v * a.first + a.second * mint::raw(len); + } +}; + +signed main() +{ + // ios::sync_with_stdio(false); + // cin.tie(0), cout.tie(0); + + using Point = pair; + LazyKDForest t; + + u32 n, q; + // cin >> n >> q; + scanf("%u %u", &n, &q); + + u32 op, a, b, c, d, e, f; + while (n--) { + // cin >> a >> b >> c; + scanf("%u %u %u", &a, &b, &c); + t.push_back({a, b}, c); + } + while (q--) { + // cin >> op; + scanf("%u", &op); + if (op == 0) { + // cin >> a >> b >> c; + scanf("%u %u %u", &a, &b, &c); + t.push_back({a, b}, c); + } + else if (op == 1) { + // cin >> a >> b; + scanf("%u %u", &a, &b); + t.set(a, b); + } + else if (op == 2) { + // cin >> a >> b >> c >> d; + scanf("%u %u %u %u", &a, &b, &c, &d); + // cout << t.prod({a, b}, {c - 1, d - 1}).val() << '\n'; + printf("%u\n", t.prod({a, b}, {c - 1, d - 1}).val()); + } + else { + // cin >> a >> b >> c >> d >> e >> f; + scanf("%u %u %u %u %u %u", &a, &b, &c, &d, &e, &f); + t.apply({a, b}, {c - 1, d - 1}, {e, f}); + } + } + return 0; +} \ No newline at end of file diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/task.md b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/task.md new file mode 100644 index 00000000..2e486529 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/task.md @@ -0,0 +1,55 @@ +## @{keyword.statement} +@{lang.en} + +You are given an initial multiset of $N$ weighted points, $P = (P_0, P_1, \dots, P_{N - 1})$, on a two-dimensional plane. Each point $P_i$ ($0 \leq i < N$) is located at $(x_i, y_i)$ and has an associated weight $w_i$. Process $Q$ queries of the following types. For the $i$-th ($0\leq i < Q$) query: + +- `0 $x$ $y$ $w$`: Append a new point $P_{i + |P|}$ with weight $w$ at coordinates $(x, y)$. If a point already exists at these coordinates, add the new point as a separate instance. + +- `1 $x$ $w$`: Update the weight of point $P_x$ to $w$. (i.e., $w_x \gets w$) + +- `2 $l$ $d$ $r$ $u$`: Calculate the sum of weights modulo $@{param.MOD}$ for all points where $l \leq x_i < r$ and $d \leq y_i < u$. + +- `3 $l$ $d$ $r$ $u$ $a$ $b$`: For each $i$ such that $l \leq x_i < r$ and $d \leq y_i < u$, apply the transformation $w_i \gets a \cdot w_i + b$. + +@{lang.ja} + +- + +@{lang.end} + +## @{keyword.constraints} +@{lang.en} + +- $1 \leq N \leq @{param.N_MAX}$ +- $1 \leq Q \leq @{param.Q_MAX}$ +- $0 \leq x_i, y_i \leq @{param.COORD_MAX}$ +- $0 \leq w_i < @{param.MOD}$ + +For each query type: +- Type `0`: $0 \leq x, y \leq @{param.COORD_MAX}$, $0 \leq w < @{param.MOD}$ +- Type `1`: $0\leq x < |P|, 0\leq w < @{param.MOD}$ +- Type `2`: $0 \leq l < r \leq @{param.COORD_MAX}$, $0 \leq d < u \leq @{param.COORD_MAX}$ +- Type `3`: $0 \leq l < r \leq @{param.COORD_MAX}$, $0 \leq d < u \leq @{param.COORD_MAX}$, $0 \leq a, b < @{param.MOD}$ + +@{lang.ja} + +- + +@{lang.end} + +## @{keyword.input} +~~~ +$N$ $Q$ +$x_0$ $y_0$ $w_0$ +$x_1$ $y_1$ $w_1$ +$x_2$ $y_2$ $w_2$ +$\hspace{17pt} \vdots$ +$x_{N - 1}$ $y_{N - 1}$ $w_{N - 1}$ +$\mathrm{Query}_0$ +$\mathrm{Query}_1$ +$\mathrm{Query}_2$ +$\hspace{13pt} \vdots$ +$\mathrm{Query}_{Q - 1}$ +~~~ + +@{example.example_00} diff --git a/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/verifier.cpp b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/verifier.cpp new file mode 100644 index 00000000..839720a2 --- /dev/null +++ b/data_structure/dynamic_point_set_rectangle_affine_rectangle_sum/verifier.cpp @@ -0,0 +1,67 @@ +#include "testlib.h" +#include "params.h" + +int main() { + registerValidation(); + + int n = inf.readInt(1, N_MAX); + inf.readChar(' '); + int q = inf.readInt(1, Q_MAX); + inf.readChar('\n'); + + for (int i = 0; i < n; i++) { + inf.readInt(0, COORD_MAX, "x"); + inf.readSpace(); + inf.readInt(0, COORD_MAX, "y"); + inf.readSpace(); + inf.readInt(0, MOD - 1, "w"); + inf.readChar('\n'); + } + + for (int i = 0; i < q; i++) { + int t = inf.readInt(0, 3); + inf.readSpace(); + if (t == 0) { + inf.readInt(0, COORD_MAX, "x"); + inf.readSpace(); + inf.readInt(0, COORD_MAX, "y"); + inf.readSpace(); + inf.readInt(0, MOD - 1, "w"); + ++n; + } + else if (t == 1) { + inf.readInt(0, n - 1, "x"); + inf.readSpace(); + inf.readInt(0, MOD - 1, "w"); + } + else if (t == 2) { + int l = inf.readInt(0, COORD_MAX); + inf.readSpace(); + int d = inf.readInt(0, COORD_MAX); + inf.readSpace(); + int r = inf.readInt(0, COORD_MAX); + inf.readSpace(); + int u = inf.readInt(0, COORD_MAX); + ensure(l < r); + ensure(d < u); + } + else { + int l = inf.readInt(0, COORD_MAX); + inf.readSpace(); + int d = inf.readInt(0, COORD_MAX); + inf.readSpace(); + int r = inf.readInt(0, COORD_MAX); + inf.readSpace(); + int u = inf.readInt(0, COORD_MAX); + ensure(l < r); + ensure(d < u); + inf.readSpace(); + inf.readInt(0, MOD - 1); + inf.readSpace(); + inf.readInt(0, MOD - 1); + } + inf.readChar('\n'); + } + inf.readEof(); + return 0; +}