1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| #include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> #define maxn 100010 #define INF 1000000000000000000 #define ll long long using namespace std;
typedef std::vector<ll> Poly; namespace Pol { const int N = 2100000; const double pi = acos(-1); struct Complex { double x, y;
Complex(double x = 0, double y = 0) : x(x), y(y) {}
friend Complex operator + (const Complex &u, const Complex &v) { return Complex(u.x + v.x, u.y + v.y); } friend Complex operator - (const Complex &u, const Complex &v) { return Complex(u.x - v.x, u.y - v.y); } friend Complex operator * (const Complex &u, const Complex &v) { return Complex(u.x * v.x - u.y * v.y, u.x * v.y + u.y * v.x); } } a[N], b[N]; int P[N]; void init_P(int n) { int l = 0; while ((1 << l) < n) ++l; for (int i = 0; i < n; ++i) P[i] = (P[i >> 1] >> 1) | ((i & 1) << l - 1); } vector<Complex> init_W(int n) { vector<Complex> w(n); w[1] = 1; for (int i = 2; i < n; i <<= 1) { auto w0 = w.begin() + i / 2, w1 = w.begin() + i; Complex wn(cos(pi / i), sin(pi / i)); for (int j = 0; j < i; j += 2) w1[j] = w0[j >> 1], w1[j + 1] = w1[j] * wn; } return w; } auto w = init_W(1 << 21); void DIT(Complex *a, int n) { for (int k = n >> 1; k; k >>= 1) for (int i = 0; i < n; i += k << 1) for (int j = 0; j < k; ++j) { Complex x = a[i + j], y = a[i + j + k]; a[i + j + k] = (x - y) * w[k + j], a[i + j] = x + y; } } void DIF(Complex *a, int n) { for (int k = 1; k < n; k <<= 1) for (int i = 0; i < n; i += k << 1) for (int j = 0; j < k; ++j) { Complex x = a[i + j], y = a[i + j + k] * w[k + j]; a[i + j + k] = x - y, a[i + j] = x + y; } for (int i = 0; i < n; ++i) a[i].x /= n, a[i].y /= n; reverse(a + 1, a + n); } Poly Mul(const Poly &A, const Poly &B, int n1, int n2) { int n = 1; while (n < n1 + n2 - 1) n <<= 1; init_P(n); for (int i = 0; i < n1; ++i) a[i] = Complex(A[i], 0); for (int i = 0; i < n2; ++i) b[i] = Complex(B[i], 0); fill(a + n1, a + n, Complex(0, 0)); fill(b + n2, b + n, Complex(0, 0)); DIT(a, n); DIT(b, n); for (int i = 0; i < n; ++i) a[i] = a[i] * b[i]; DIF(a, n); Poly ans(n1 + n2 - 1); for (int i = 0; i < n1 + n2 - 1; ++i) ans[i] = (ll) (a[i].x + 0.5); return ans; } }
int n; ll a[maxn], b[maxn];
ll ans[2][maxn]; void solve(ll *ans) { sort(a + 1, a + n + 1); sort(b + 1, b + n + 1); int pre = 0, suf = n + 1; for (int i = 1; i <= n; ++i) if (a[i] <= 0 && b[i] <= 0) pre = i; for (int i = n; i; --i) if (a[i] > 0 && b[i] > 0) suf = i; int k = suf - pre - 1; for (int o = 1, p = 1, s = n; o <= n - k; ++o) { ans[o] = max({ 0ll, a[p] * b[p], a[s] * b[s] }); if (p <= pre && ans[o] == a[p] * b[p]) ++p; else --s; ans[o] += ans[o - 1]; } if (!k) return ; Poly A(k), B(k); for (int i = 0; i < k; ++i) A[i] = a[pre + i + 1], B[i] = b[pre + i + 1]; if (A[0] < 0) { for (auto &t : A) t = -t; reverse(A.begin(), A.end()); } else { for (auto &t : B) t = -t; reverse(B.begin(), B.end()); } Poly res = Pol::Mul(A, B, k, k); for (int i = 0; i < k; ++i) ans[i + n - k + 1] = ans[n - k] - res[i]; }
int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> n; for (int i = 1; i <= n; ++i) cin >> a[i]; for (int i = 1; i <= n; ++i) cin >> b[i]; solve(ans[1]); for (int i = 1; i <= n; ++i) a[i] = -a[i]; solve(ans[0]); for (int i = 1; i <= n; ++i) cout << -ans[0][i] << " " << ans[1][i] << "\n"; return 0; }
|