Problem: Problem

Given a sequence $ A $ of length $ H $ and a sequence $ B $ of length $ W $.

Define the matrix $ C $ consisting of $ H $ rows and $ W $ columns as follows.
$ C_ {i, j} = A_i \ times B_j (1 \ leq i \ leq H, 1 \ leq j \ leq W) $

Process the following four types of queries a total of $ Q $ times.

Query 1
$ 1 $ $ a $ $ b $ $ v $
$ A_i (a \ leq i \ leq b) Add $ v $ to $

Query 2
$ 2 $ $ c $ $ d $ $ v $
$ B_j (c \ leq j \ leq d) Add $ v $ to $

Query 3
$ 3 $ $ a $ $ b $ $ c $ $ d $
$ C_ {i, j} (a \ leq i \ leq b, c \ leq j \ leq d) Output the minimum value of $ and its number

Query 4
$ 4 $ $ a $ $ b $ $ c $ $ d $
$ C_ {i, j} (a \ leq i \ leq b, c \ leq j \ leq d) Output the maximum value of $ and its number

For details, refer to sample input / output.

Constraints

The input satisfies the following conditions.

* $ 1 \ leq H, W, Q \ leq 10 ^ 5 $
* $ -1000 \ leq A_i \ leq 1000 $
* $ -1000 \ leq B_j \ leq 1000 $



For each query, the input satisfies the following conditions.


* $ 1 \ leq a \ leq b \ leq H $
* $ 1 \ leq c \ leq d \ leq W $
* $ -1000 \ leq v \ leq 1000 $

Input

The input is given in the following format.


$ H $ $ W $ $ Q $
$ A_1 $ $ A_2 $ ... $ A_H $
$ B_1 $ $ B_2 $ ... $ B_W $
$ query_1 $
$ query_2 $
...
$ query_Q $


Each query is given in one of the following four formats.


$ 1 $ $ a $ $ b $ $ v $
$ 2 $ $ c $ $ d $ $ v $
$ 3 $ $ a $ $ b $ $ c $ $ d $
$ 4 $ $ a $ $ b $ $ c $ $ d $


All inputs are given as integers.
$ H $, $ W $, $ Q $ are given on the first line, separated by blanks.
In the second row, the element $ A_i $ ($ 1 \ leq i \ leq H $) of the sequence $ A $ is given, separated by blanks.
In the third row, the element $ B_j $ ($ 1 \ leq j \ leq W $) of the sequence $ B $ is given, separated by blanks.
Queries are given on the 4th and subsequent $ Q $ lines, separated by line breaks.
All numbers in each query are separated by blanks.

Output

For each query 3 and query 4, output the value and number on one line, separated by blanks.

Examples

Input

4 4 7
1 2 3 4
1 2 3 4
3 2 3 2 3
4 2 3 2 3
3 1 1 1 1
4 1 1 1 1
1 1 1 1
3 1 4 1 2
4 2 3 2 4


Output

4 1
9 1
1 1
1 1
2 2
12 1


Input

4 4 6
1 1 1 1
1 1 1 1
3 1 4 1 4
4 1 4 1 4
1 2 3 1
2 2 3 1
3 1 4 1 4
4 1 4 1 4


Output

1 16
1 16
1 4
4 4


Input

4 4 7
0 1 0 1
1 0 1 0
3 2 4 1 3
4 1 4 1 4
1 1 4 -1
3 1 3 1 3
1 3 3 2
2 3 3 -2
3 2 4 2 4


Output

0 5
1 4
-1 4
-1 1


Input

36 4 20
-523 -460 -536 -885 652 782 513 -558 -521 -808 124 -708 -943 52 -856 -755 -958 913 380 -767 373 -731 -492 213 538 392 -39 509 -840 135 78 -285 -241 522 -572 -915
-691 -16 812 -385
4 7 17 4 4
3 24 33 1 1
4 3 35 2 4
3 28 32 4 4
2 3 3 438
3 7 15 1 1
4 2 17 4 4
3 24 28 2 4
4 15 16 4 4
4 18 29 1 1
3 24 27 2 4
2 2 3 -828
3 18 23 3 3
1 27 31 -701
2 2 3 298
1 21 32 237
2 3 3 -71
1 14 29 772
4 13 19 3 3
3 19 34 1 2


Output

368830 1
-371758 1
741356 1
-195965 1
-354483 1
368830 1
-207130 1
329560 1
580440 1
-207130 1
-323674 1
1093565 1
-1068977 1

Solution (in CPP):

Solution:
#include <bits/stdc++.h>

using namespace std;
using ll = long long;
#define int ll
using VI = vector<int>;
using VVI = vector<VI>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define PB push_back

const ll LLINF = (1LL<<60);

// 遅延セグメントツリー
template <typename T, typename E>
struct segtree {
  using F = function<T(T,T)>;
  using G = function<T(T,E)>;
  using H = function<E(E,E)>;
  using P = function<E(E,int)>;
  F f; G g; H h; P p; T d1; E d0;
  int n;
  vector<T> dat;
  vector<E> lazy;

  segtree(){}
  segtree(int n_, F f_, G g_, H h_, T d1_, E d0_, P p_=[](E a, int b){return a;}):
    f(f_), g(g_), h(h_), p(p_), d1(d1_), d0(d0_) {
    n = 1; while(n < n_) n *= 2;
    dat.assign(n*2, d1);
    lazy.assign(n*2, d0);
  }
  void build(vector<T> v) {
    REP(i, v.size()) dat[i+n-1] = v[i];
    for(int i=n-2; i>=0; --i) dat[i] = f(dat[i*2+1], dat[i*2+2]);
  }

  // 区間の幅がlenの節点kについて遅延評価
  inline void eval(int len, int k) {
    if(lazy[k] == d0) return;
    if(k*2+1 < n*2-1) {
      lazy[2*k+1] = h(lazy[k*2+1], lazy[k]);
      lazy[2*k+2] = h(lazy[k*2+2], lazy[k]);
    }
    dat[k] = g(dat[k],p(lazy[k],len));
    lazy[k] = d0;
  }
  // [a, b)
  T update(int a, int b, E x, int k, int l, int r) {
    eval(r-l, k);
    if(b <= l || r <= a) return dat[k];
    if(a <= l && r <= b) {
      lazy[k] = h(lazy[k], x);
      return g(dat[k], p(lazy[k],r-l));
    }
    return dat[k] = f(update(a, b, x, 2*k+1, l, (l+r)/2),
                      update(a, b, x, 2*k+2, (l+r)/2, r));
  }
  T update(int a, int b, E x) { return update(a, b, x, 0, 0, n); }
  // [a, b)
  T query(int a, int b, int k, int l, int r) {
    eval(r-l, k);
    if(a <= l && r <= b) return dat[k];
    bool left = !((l+r)/2 <= a || b <= l), right = !(r <= 1 || b <= (l+r)/2);
    if(left&&right) return f(query(a, b, 2*k+1, l, (l+r)/2), query(a, b, 2*k+2, (l+r)/2, r));
    if(left) return query(a, b, 2*k+1, l, (l+r)/2);
    return query(a, b, 2*k+2, (l+r)/2, r);
  }
  T query(int a, int b) { return query(a, b, 0, 0, n); }
};

signed main(void)
{
  int H, W, q;
  scanf("%lld%lld%lld", &H, &W, &q);
  VI a(H), b(W);
  REP(i, H) scanf("%lld", &a[i]);
  REP(i, W) scanf("%lld", &b[i]);

  // セグ木を定義
  auto f = [](VI a, VI b) {
    // max,minの数
    int maxnum = a[0]==max(a[0],b[0])?a[1]:0;
    maxnum += b[0]==max(a[0],b[0])?b[1]:0;
    int minnum = a[2]==min(a[2],b[2])?a[3]:0;
    minnum += b[2]==min(a[2],b[2])?b[3]:0;
    return VI{
      max(a[0],b[0]),
      maxnum,
      min(a[2],b[2]),
      minnum
    };
  };
  auto g = [](VI a, int b) {
    return VI{
      a[0]+b,
      a[1],
      a[2]+b,
      a[3]
    };
  };
  auto h = [](int a, int b) {
    return a+b;
  };
  segtree<VI,int> seg1(H, f, g, h, {0,1,0,1}, 0),
                 seg2(W, f, g, h, {0,1,0,1}, 0);

  // 初期状態を設定
  VVI inita, initb;
  REP(i, H) inita.PB({a[i], 1, a[i], 1});
  REP(i, W) initb.PB({b[i], 1, b[i], 1});
  seg1.build(inita); seg2.build(initb);

  // クエリにこたえる
  REP(i, q) {
    int type;
    scanf("%lld", &type);
    if(type==1) {
      int a, b, v;
      scanf("%lld%lld%lld", &a, &b, &v);
      seg1.update(a-1, b, v);
    } else if(type==2) {
      int a, b, v;
      scanf("%lld%lld%lld", &a, &b, &v);
      seg2.update(a-1, b, v);
    } else if(type==4) {
      int ma = -LLINF, num = 0;
      int a, b, c, d;
      scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
      VI v1 = seg1.query(a-1, b);
      VI v2 = seg2.query(c-1, d);
      ma = max({
        v1[0]*v2[0],
        v1[2]*v2[2],
        v1[0]*v2[2],
        v1[2]*v2[0]
      });
      // maxが0のケース
      if(ma == 0) {
        int tmpa = 0, tmpb = 0;
        if(v1[0] == 0) tmpa = v1[1];
        if(v1[2] == 0) tmpa = v1[3];
        if(v2[0] == 0) tmpb = v2[1];
        if(v2[2] == 0) tmpb = v2[3];
        num = (b-a+1)*(d-c+1) - (b-a+1-tmpa)*(d-c+1-tmpb);
      } else {
        if(v1[0] == v1[2] && v2[0] == v2[2]) {
          num = (b-a+1) * (d-c+1);
        } else if(v1[0] == v1[2] || v2[0] == v2[2]) {
          if(v1[2]*v2[2] == ma) num += v1[3]*v2[3];
          if(v1[0]*v2[0] == ma) num += v1[1]*v2[1];
        } else {
          if(v1[0]*v2[0] == ma) num += v1[1]*v2[1];
          if(v1[0]*v2[2] == ma) num += v1[1]*v2[3];
          if(v1[2]*v2[0] == ma) num += v1[3]*v2[1];
          if(v1[2]*v2[2] == ma) num += v1[3]*v2[3];
        }
      }
      printf("%lld %lld\n", ma, num);
    } else if(type==3) {
      int mi = LLINF, num = 0;
      int a, b, c, d;
      scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
      VI v1 = seg1.query(a-1, b);
      VI v2 = seg2.query(c-1, d);
      mi = min({
        v1[0]*v2[0],
        v1[2]*v2[2],
        v1[0]*v2[2],
        v1[2]*v2[0]
      });
      // minが0の場合
      if(mi == 0) {
        int tmpa = 0, tmpb = 0;
        if(v1[0] == 0) tmpa = v1[1];
        if(v1[2] == 0) tmpa = v1[3];
        if(v2[0] == 0) tmpb = v2[1];
        if(v2[2] == 0) tmpb = v2[3];
        num = (b-a+1)*(d-c+1) - (b-a+1-tmpa)*(d-c+1-tmpb);
      } else {
        if(v1[0] == v1[2] && v2[0] == v2[2]) {
          num = (b-a+1) * (d-c+1);
        } else if(v1[0] == v1[2] || v2[0] == v2[2]) {
          if(v1[2]*v2[2] == mi) num += v1[3]*v2[3];
          if(v1[0]*v2[0] == mi) num += v1[1]*v2[1];
        } else {
          if(v1[0]*v2[0] == mi) num += v1[1]*v2[1];
          if(v1[0]*v2[2] == mi) num += v1[1]*v2[3];
          if(v1[2]*v2[0] == mi) num += v1[3]*v2[1];
          if(v1[2]*v2[2] == mi) num += v1[3]*v2[3];
        }
      }
      printf("%lld %lld\n", mi, num);
    }
  }

  return 0;
}