Skip to content

Commit 9ab2bb6

Browse files
authored
Merge pull request #1335 from NachiaVivias/minplus_func
Min-Plus Convolution 3 問に C++(Function) サポートを追加
2 parents b98c19e + 39dc2d9 commit 9ab2bb6

12 files changed

Lines changed: 342 additions & 0 deletions

File tree

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <chrono>
2+
#include <iostream>
3+
#include <utility>
4+
5+
#include "fastio.h"
6+
#include "solve.hpp"
7+
8+
using namespace std::chrono;
9+
using namespace library_checker;
10+
11+
int main() {
12+
Scanner sc = Scanner(stdin);
13+
Printer pr = Printer(stdout);
14+
15+
int n = 0, m = 0;
16+
sc.read(n, m);
17+
18+
std::vector<int> a(n), b(m);
19+
for (int i = 0; i < n; i++) {
20+
sc.read(a[i]);
21+
}
22+
for (int i = 0; i < m; i++) {
23+
sc.read(b[i]);
24+
}
25+
26+
steady_clock::time_point begin = steady_clock::now();
27+
auto ans = solve(std::move(a), std::move(b));
28+
steady_clock::time_point end = steady_clock::now();
29+
30+
auto elapsed_time = duration_cast<milliseconds>(end - begin);
31+
std::cerr << "solve() consumes: " << elapsed_time.count() << "ms"
32+
<< std::endl;
33+
34+
for (int i = 0; i <= (n - 1) + (m - 1); i++) {
35+
if (i) pr.write(' ');
36+
pr.write(ans[i]);
37+
}
38+
pr.writeln();
39+
40+
return 0;
41+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include <vector>
2+
3+
std::vector<int> solve(std::vector<int> a, std::vector<int> b);

convolution/min_plus_convolution_concave_arbitrary/info.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ forum = "https://github.com/yosupo06/library-checker-problems/issues/1252"
5050
name = "naive.cpp"
5151
allow_tle = true
5252

53+
[[solutions]]
54+
name = "ac_func.cpp"
55+
function = true
56+
5357
[params]
5458
N_MAX = 524288
5559
A_MIN = 0
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#include <cstdio>
2+
#include <vector>
3+
#include <cassert>
4+
#include <limits>
5+
#include <functional>
6+
7+
using namespace std;
8+
9+
10+
template <class FUNC>
11+
vector<int> monotone_minima(int h, int w, const FUNC& a) {
12+
vector<int> j_min(h);
13+
14+
for (int di = 1 << 20; di > 0; di >>= 1) {
15+
int di2 = 2 * di;
16+
for (int i = di; i <= h; i += di2) {
17+
int jL = (i - di > 0 ? j_min[i - di - 1] : 0);
18+
int jR = (i + di <= h ? j_min[i + di - 1] : w - 1);
19+
20+
int a_min = numeric_limits<int>::max();
21+
for (int j = jL; j <= jR; j++) {
22+
int val = a(i - 1, j);
23+
24+
if (a_min > val) {
25+
a_min = val;
26+
j_min[i - 1] = j;
27+
}
28+
}
29+
}
30+
}
31+
32+
return j_min;
33+
}
34+
35+
36+
vector<int> solve(vector<int> b, vector<int> a) {
37+
int n = (int)a.size(), m = (int)b.size();
38+
39+
// b is concave
40+
for (int i = 0; i < m - 2; ++i) assert(b[i] + b[i + 2] <= 2 * b[i + 1]);
41+
42+
int h = n + m - 1, w = n;
43+
44+
vector<int> y_min(h, 0), y_max(h, w - 1);
45+
for (int x = m; x <= h - 1; x++) y_min[x] = x - m + 1;
46+
for (int x = 0; x <= h - m; x++) y_max[x] = x;
47+
48+
vector<int> x_min(w), x_max(w);
49+
for (int y = 0; y < w; y++) {
50+
x_min[y] = y;
51+
x_max[y] = m - 1 + y;
52+
}
53+
54+
vector<int> c(h, numeric_limits<int>::max());
55+
56+
function<void(int, int, int, int)> rf = [&](int x1, int x2, int y1, int y2) {
57+
if (y_max[x1] >= y2 && y1 >= y_min[x2]) {
58+
auto A = [&](int i, int j) {
59+
return a[y2 - j] + b[(x1 + i) - (y2 - j)];
60+
};
61+
62+
auto j_min = monotone_minima(x2 - x1 + 1, y2 - y1 + 1, A);
63+
64+
for (int i = x1; i <= x2; i++) {
65+
int val = A(i - x1, j_min[i - x1]);
66+
if (c[i] > val) c[i] = val;
67+
}
68+
69+
return;
70+
}
71+
72+
if ((long long)(x2 - x1) * (y2 - y1) < 1000) {
73+
for (int x = x1; x <= x2; x++) {
74+
int y_from = max(y_min[x], y1);
75+
int y_to = min(y_max[x], y2);
76+
for (int y = y_from; y <= y_to; y++) {
77+
int val = a[y] + b[x - y];
78+
if (c[x] > val) c[x] = val;
79+
}
80+
}
81+
return;
82+
}
83+
84+
if (x2 - x1 > y2 - y1) {
85+
int xm = (x1 + x2) / 2;
86+
87+
int ny2 = min(y_max[xm], y2);
88+
if (y1 <= ny2) rf(x1, xm, y1, ny2);
89+
90+
int ny1 = max(y_min[xm], y1);
91+
if (ny1 <= y2) rf(xm + 1, x2, ny1, y2);
92+
}
93+
else {
94+
int ym = (y1 + y2) / 2;
95+
96+
int nx2 = min(x_max[ym], x2);
97+
if (x1 <= nx2) rf(x1, nx2, y1, ym);
98+
99+
int nx1 = max(x_min[ym], x1);
100+
if (nx1 <= x2) rf(nx1, x2, ym + 1, y2);
101+
}
102+
};
103+
rf(0, h - 1, 0, w - 1);
104+
105+
return c;
106+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <chrono>
2+
#include <iostream>
3+
#include <utility>
4+
5+
#include "fastio.h"
6+
#include "solve.hpp"
7+
8+
using namespace std::chrono;
9+
using namespace library_checker;
10+
11+
int main() {
12+
Scanner sc = Scanner(stdin);
13+
Printer pr = Printer(stdout);
14+
15+
int n = 0, m = 0;
16+
sc.read(n, m);
17+
18+
std::vector<int> a(n), b(m);
19+
for (int i = 0; i < n; i++) {
20+
sc.read(a[i]);
21+
}
22+
for (int i = 0; i < m; i++) {
23+
sc.read(b[i]);
24+
}
25+
26+
steady_clock::time_point begin = steady_clock::now();
27+
auto ans = solve(std::move(a), std::move(b));
28+
steady_clock::time_point end = steady_clock::now();
29+
30+
auto elapsed_time = duration_cast<milliseconds>(end - begin);
31+
std::cerr << "solve() consumes: " << elapsed_time.count() << "ms"
32+
<< std::endl;
33+
34+
for (int i = 0; i <= (n - 1) + (m - 1); i++) {
35+
if (i) pr.write(' ');
36+
pr.write(ans[i]);
37+
}
38+
pr.writeln();
39+
40+
return 0;
41+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include <vector>
2+
3+
std::vector<int> solve(std::vector<int> a, std::vector<int> b);

convolution/min_plus_convolution_convex_arbitrary/info.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ forum = "https://github.com/yosupo06/library-checker-problems/issues/727"
5050
name = "naive.cpp"
5151
allow_tle = true
5252

53+
[[solutions]]
54+
name = "ac_func.cpp"
55+
function = true
56+
5357
[params]
5458
N_MAX = 524288
5559
A_MIN = 0
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include <iostream>
2+
#include <cstdio>
3+
#include <vector>
4+
#include <cassert>
5+
6+
using namespace std;
7+
8+
template <typename T>
9+
using vc = vector<T>;
10+
11+
// select(i,j,k) : (i,j) -> (i,k)
12+
template <typename F>
13+
vc<int> monotone_minima(int H, int W, F select) {
14+
vc<int> min_col(H);
15+
auto dfs = [&](auto& dfs, int x1, int x2, int y1, int y2) -> void {
16+
if (x1 == x2) return;
17+
int x = (x1 + x2) / 2;
18+
int best_y = y1;
19+
for (int y = y1 + 1; y < y2; ++y) {
20+
if (select(x, best_y, y)) best_y = y;
21+
}
22+
min_col[x] = best_y;
23+
dfs(dfs, x1, x, y1, best_y + 1);
24+
dfs(dfs, x + 1, x2, best_y, y2);
25+
};
26+
dfs(dfs, 0, H, 0, W);
27+
return min_col;
28+
}
29+
30+
vc<int> solve(vc<int> B, vc<int> A) {
31+
int N = A.size(), M = B.size();
32+
// B is convex
33+
for (int i = 0; i < M - 2; ++i) assert(B[i] + B[i + 2] >= 2 * B[i + 1]);
34+
auto select = [&](int i, int j, int k) -> bool {
35+
if (i < k) return false;
36+
if (i - j >= M) return true;
37+
return A[j] + B[i - j] >= A[k] + B[i - k];
38+
};
39+
vc<int> J = monotone_minima(N + M - 1, N, select);
40+
vc<int> C(N + M - 1);
41+
for (int i = 0; i < N + M - 1; ++i) {
42+
int j = J[i];
43+
C[i] = A[j] + B[i - j];
44+
}
45+
return C;
46+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <chrono>
2+
#include <iostream>
3+
#include <utility>
4+
5+
#include "fastio.h"
6+
#include "solve.hpp"
7+
8+
using namespace std::chrono;
9+
using namespace library_checker;
10+
11+
int main() {
12+
Scanner sc = Scanner(stdin);
13+
Printer pr = Printer(stdout);
14+
15+
int n = 0, m = 0;
16+
sc.read(n, m);
17+
18+
std::vector<int> a(n), b(m);
19+
for (int i = 0; i < n; i++) {
20+
sc.read(a[i]);
21+
}
22+
for (int i = 0; i < m; i++) {
23+
sc.read(b[i]);
24+
}
25+
26+
steady_clock::time_point begin = steady_clock::now();
27+
auto ans = solve(std::move(a), std::move(b));
28+
steady_clock::time_point end = steady_clock::now();
29+
30+
auto elapsed_time = duration_cast<milliseconds>(end - begin);
31+
std::cerr << "solve() consumes: " << elapsed_time.count() << "ms"
32+
<< std::endl;
33+
34+
for (int i = 0; i <= (n - 1) + (m - 1); i++) {
35+
if (i) pr.write(' ');
36+
pr.write(ans[i]);
37+
}
38+
pr.writeln();
39+
40+
return 0;
41+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include <vector>
2+
3+
std::vector<int> solve(std::vector<int> a, std::vector<int> b);

0 commit comments

Comments
 (0)