//#define NDEBUG
#define _CRT_SECURE_NO_WARNINGS
#include <algorithm>
#include <array>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
constexpr double PI = 3.1415926535897932;

using int32 = std::int_fast64_t;
using int64 = std::int_fast64_t;
using uint32 = std::uint_fast64_t;
using uint64 = std::uint_fast64_t;
using intl32 = std::int_least32_t;
using intl64 = std::int_least64_t;
using uintl32 = std::uint_least32_t;
using uintl64 = std::uint_least64_t;

const char *yes(bool c) { return c ? "yes" : "no"; }
const char *Yes(bool c) { return c ? "Yes" : "No"; }
const char *YES(bool c) { return c ? "YES" : "NO"; }
const char *pos(bool c) { return c ? "possible" : "impossible"; }
const char *Pos(bool c) { return c ? "Possible" : "Impossible"; }
const char *POS(bool c) { return c ? "POSSIBLE" : "IMPOSSIBLE"; }
template<class T>bool bmaxi(T&a, const T&b) { if (b<a)return 0;a = b;return 1; }
template<class T>bool bmini(T&a, const T&b) { if (a<b)return 0;a = b;return 1; }
template<class T>bool nmaxi(T&a, const T&b) { if (a<b) { a = b;return 1; }return 0; }
template<class T>bool nmini(T&a, const T&b) { if (b<a) { a = b;return 1; }return 0; }
template<typename T>auto scan(T&d)->typename std::enable_if<std::is_signed<T>::value>::type
{
	d = 0;int c = fgetc(stdin);bool f = 0;while (c<'0' || '9'<c) { if (c == '-')f = 1;c = fgetc(stdin); }
	while (c != ' '&&c != '\n') { d = d * 10 + c - '0';c = fgetc(stdin); }if (f)d = -d;
}
template<typename T>auto scan(T&d)->typename std::enable_if<!std::is_signed<T>::value>::type
{
	d = 0;int c = fgetc(stdin);while (c == ' ' || c == '\n')c = fgetc(stdin);
	while (c != ' '&&c != '\n') { d = d * 10 + c - '0';c = fgetc(stdin); }
}
void scan(char&d) { d = fgetc(stdin);while (d == ' ' || d == '\n')d = fgetc(stdin); }
void scan(double&d) { scanf("%lf", &d); }void scan(std::string&d) {
	d.clear();int c = fgetc(stdin);
	while (c == ' ' || c == '\n')c = fgetc(stdin);while (c != ' '&&c != '\n') { d.push_back(c);c = fgetc(stdin); }
}
template<typename F, typename...R>void scan(F&f, R&...r) { scan(f);scan(r...); }
template<typename T>T in() { T d;scan(d);return d; }
template <typename T>auto print(T d)->typename std::enable_if<std::is_signed<T>::value>::type
{
	static int c[20];int i = 0;bool f = 0;if (d<0) { f = 1;d = -d; }while (d) { c[i++] = d % 10;d /= 10; }
	if (!i)c[i++] = 0;if (f)fputc('-', stdout);while (i--)fputc(c[i] + '0', stdout);
}
template<typename T>auto print(T d)->typename std::enable_if<!std::is_signed<T>::value>::type
{
	static int c[20];int i = 0;while (d) { c[i++] = d % 10;d /= 10; }
	if (!i)c[i++] = 0;while (i--)fputc(c[i] + '0', stdout);
}
template<>void print<char>(char d) { fputc(d, stdout); }
template<>void print<double>(double d) { printf("%f", d); }
template<>void print<char *>(char *c) { while (*c != '\0')fputc(*(c++), stdout); }void print() {}
template<typename F, typename...R>void print(F f, R...r) { print(f);print(r...); }
template<typename...R>void println(R...r) { print(r...);fputc('\n', stdout); }
template<typename...R>int END(R...r) { println(r...);return 0; }
#ifndef __GNUC__
std::uint_fast32_t __builtin_popcount(std::uint_fast32_t c) {
	c = (c & 0x55555555) + ((c >> 1) & 0x55555555);
	c = (c & 0x33333333) + ((c >> 2) & 0x33333333);
	c = (c + (c >> 4)) & 0x0F0F0F0F;
	c += c >> 8;
	c += c >> 16;
	return c & 0x3F;
}
#endif

template<typename Monoid, typename Operand>
class lazy_segment_tree {
	struct node {
		Monoid element;
		Operand lazy;
		bool h;
	};
	std::vector<node> tree;
	std::uint_fast32_t size, height;
	void assign(std::uint_fast32_t index, const Operand &data) {
		if (tree[index].h) tree[index].lazy = tree[index].lazy*data;
		else { tree[index].lazy = data;tree[index].h = 1; }
	}
	Monoid reflect(std::uint_fast32_t index) {
		if (tree[index].h) return tree[index].element*tree[index].lazy;
		return tree[index].element;
	}
	void recalc(std::uint_fast32_t index) {
		tree[index].element = reflect(index << 1) + reflect(index << 1 | 1);
	}
	void push(std::uint_fast32_t index) {
		if (!tree[index].h) return;
		assign(index << 1, tree[index].lazy);
		assign(index << 1 | 1, tree[index].lazy);
		tree[index].element = tree[index].element*tree[index].lazy;
		tree[index].h = 0;
	}
	void propagate(std::uint_fast32_t index) {
		std::uint_fast32_t i = height;
		do { push(index >> i); } while (--i);
	}
	void build(std::uint_fast32_t index) {
		while (index >>= 1)recalc(index);
	}
public:
	void update(std::uint_fast32_t begin, std::uint_fast32_t end, const Operand &data) {
		begin += size;
		end += size - 1;
		propagate(begin);
		propagate(end);
		for (std::uint_fast32_t left = begin, right = end + 1;left < right;left >>= 1, right >>= 1) {
			if (left & 1) assign(left++, data);
			if (right & 1) assign(--right, data);
		}
		build(begin);
		build(end);
	}
	Monoid range(std::uint_fast32_t begin, std::uint_fast32_t end) {
		begin += size;end += size;
		propagate(begin);
		propagate(end - 1);
		Monoid retL, retR;
		for (;begin < end;begin >>= 1, end >>= 1) {
			if (begin & 1) retL = retL + reflect(begin++);
			if (end & 1) retR = reflect(--end) + retR;
		}
		return retL + retR;
	}
	//true��Ԃ��ŏ��̃C���f�b�N�X
	std::uint_fast32_t binary_search(std::function<bool(Monoid)> bound) {
		if (!bound(reflect(1))) return size;
		Monoid ret;
		std::uint_fast32_t i = 1;
		while (i < size) {
			push(i);
			if (!bound(ret + reflect(i <<= 1))) ret = ret + reflect(i++);
		}
		return i - size;
	}
	lazy_segment_tree(std::uint_fast32_t length) :height(static_cast<std::uint_fast32_t>(0)) {
		--length;
		length |= length >> 1;
		length |= length >> 2;
		length |= length >> 4;
		length |= length >> 8;
		length |= length >> 16;
		if (!length) length = 1;
		height = __builtin_popcount(length);
		size = length + 1;
		tree = std::vector<node>(size << 1);
		initialize();
	}
	void update(std::uint_fast32_t index, std::function<Monoid(const Monoid &)> f) {
		index += size;
		propagate(index);
		if (tree[index].h) {
			tree[index].element = tree[index].element*tree[index].lazy;
			tree[index].h = 0;
		}
		tree[index].element = f(tree[index].element);
		build(index);
	}
	void initialize(void) {
		std::uint_fast32_t const s = size;
		std::uint_fast32_t i = s << 1;
		while (--i >= s) { tree[i].element = Monoid();tree[i].h = 0; }
		do { recalc(i);tree[i].h = 0; } while (--i);
	}
};
struct add {
	int64 a;
	add(int64 t=0):a(t){}
	add operator*(const add &o)const {
		return add(a + o.a);
	}
};
struct Mo {
	int64 i, a;
	uint64 ni, na;
	bool op;
	Mo():op(1){}
	Mo(int64 x,int64 y,uint64 z,uint64 w):i(x),a(y),ni(z),na(w),op(0){}
	Mo operator+(const Mo &o)const{
		if (op) return o;
		if (o.op) return *this;
		int64 ri = std::min(i, o.i), ra = std::max(a, o.a);
		uint64 rni = 0, rna = 0;
		if (ri == i) rni += ni;
		if (ra == a)rna += na;
		if (ri == o.i) rni += o.ni;
		if (ra == o.a) rna += o.na;
		return Mo(ri, ra, rni, rna);
	}
	Mo operator*(const add &o)const {
		if (op) return *this;
		return Mo(i + o.a, a + o.a, ni, na);
	}
};

int main(void) {
	uint32 h, w, q;
	scan(h, w, q);
	std::vector<Mo> aa(h), bb(w);
	for (auto &x : aa) {
		int64 t = in<int64>();
		x.i = x.a = t;
		x.ni = x.na = 1;
		x.op = 0;
	}
	for (auto &x : bb) {
		int64 t = in<int64>();
		x.i = x.a = t;
		x.ni = x.na = 1;
		x.op = 0;
	}
	lazy_segment_tree<Mo, add> T(h), U(w);
	for (uint32 i = 0;i < h;++i)T.update(i, [&](const Mo &o)->Mo {return aa[i];});
	for (uint32 i = 0;i < w;++i)U.update(i, [&](const Mo &o)->Mo {return bb[i];});
	while (q--) {
		uint32 x;
		scan(x);
		uint32 a, b, c, d;
		add v;
		if (x == 1 || x == 2) {
			scan(a, b, v.a);
			if (x == 1)T.update(a - 1, b, v);
			else U.update(a - 1, b, v);
		}
		else {
			scan(a, b, c, d);
			Mo t = T.range(a - 1, b);
			Mo u = U.range(c - 1, d);
			if (x == 3) {
				if (t.i > 0 && u.i > 0) {
					println(t.i*u.i, ' ', t.ni*u.ni);
				}
				else if (t.a < 0 && u.a < 0) {
					println(t.a*u.a, ' ', t.na*u.na);
				}
				else {
					int64 ans = std::min(t.i*u.a, t.a*u.i);
					uint64 num = 0;
					if (ans == t.i*u.a) {
						num += t.ni*u.na;
					}
					if (ans == t.a*u.i) {
						num += t.na*u.ni;
					}
					if (t.i == t.a&&u.i == u.a)num /= 2;
					if (ans == 0) {
						num = 0;
						if (t.i >= 0&&u.i>=0) {
							if (t.i == 0) num += t.ni*(d - c + 1);
							if (u.i == 0) num += u.ni*(b - a + 1);
							if (t.i == 0 && u.i == 0) num -= t.ni*u.ni;
						}
						else {
							if (t.a == 0) num += t.na*(d - c + 1);
							if (u.a == 0) num += u.na*(b - a + 1);
							if (t.a == 0 && u.a == 0)num -= t.na*u.na;
						}
					}
					println(ans, ' ', num);
				}
			}
			else {
				if (t.i > 0 && u.a < 0) {
					println(t.i*u.a, ' ', t.ni*u.na);
				}
				else if (t.a < 0 && u.i > 0) {
					println(t.a*u.i, ' ', t.na*u.ni);
				}
				else {
					int64 ans = std::max(t.i*u.i, t.a*u.a);
					uint64 num = 0;
					if (ans == t.i*u.i) {
						num += t.ni*u.ni;
					}
					if (ans == t.a*u.a) {
						num += t.na*u.na;
					}
					if (t.i == t.a&&u.i == u.a)num /= 2;
					if (ans == 0) {
						num = 0;
						if (t.i >= 0 && u.i <= 0) {
							if (t.i == 0) num += t.ni*(d - c + 1);
							if (u.a == 0) num += u.na*(b - a + 1);
							if (t.i == 0 && u.a == 0) num -= t.ni*u.na;
						}
						else {
							if (t.a == 0) num += t.na*(d - c + 1);
							if (u.i == 0) num += u.ni*(b - a + 1);
							if (t.a == 0 && u.i == 0)num -= t.na*u.ni;
						}
					}
					println(ans, ' ', num);
				}
			}
		}
	}
	return 0;
}


Measured memory_bytes: 37880