#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<numeric>
#include<functional>
#include<algorithm>
#include<bitset>
#include<tuple>
#include<unordered_set>
#include<unordered_map>
#include<random>
#include<array>
#include<cassert>
using namespace std;
#define INF ((1<<30)-1)
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(v) v.begin(),v.end()


struct TrieNode{
	int n = 0;
	long long sum = 0;
	TrieNode* l = nullptr, * r = nullptr;
};

class Trie {
public:
	Trie() { root = new TrieNode(); }

	void insert(int x) {
		TrieNode* t = root;
		for (int i = 30; i >= 0; i--) {
			t->n++;
			t->sum += x;
			if (x >> i &1) {
				if (t->r == nullptr) t->r = new TrieNode;
				t = t->r;
			}
			else {
				if (t->l == nullptr) t->l = new TrieNode;
				t = t->l;
			}
		}
		t->n++;
		t->sum += x;
	}

	void erase(int x) {
		TrieNode* t = root;
		for (int i = 30; i >= 0; i--) {
			t->n--;
			t->sum -= x;
			if (x >> i & 1) {
				t = t->r;
			}
			else {
				t = t->l;
			}
		}
		t->n--;
		t->sum -= x;
	}

	pair<int, long long> query(int x) const{
		pair<int, long long > ret(0, 0);
		TrieNode* t = root;
		for (int i = 30; i >= 0; i--) {
			if (t == nullptr)break;
			if (x >> i & 1) {
				if (t->l) {
					ret.first += t->l->n;
					ret.second += t->l->sum;
				}
				t = t->r;
			}
			else {
				t = t->l;
			}
		}
		return ret;
	}
private:
	TrieNode* root;
};



int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	int n, m, q;
	cin >> n >> m >> q;

	vector<int> a(n, 0), b(m, 0);

	Trie ta, tb;
	rep(i, n) ta.insert(0);
	rep(i, m)tb.insert(0);

	long long ans = 0;
	rep(_, q) {
		int t, x, y;
		cin >> t >> x >> y;
		x--;

		if (t == 1) {
			auto p = tb.query(a[x]);
			ans -= (long long)p.first * a[x];
			ans += p.second;
		
			p = tb.query(y);
			ans += (long long)p.first * y;
			ans -= p.second;

			ta.erase(a[x]);
			ta.insert(y);
			a[x] = y;
		}
		else {
			auto p = ta.query(b[x]);
			ans -= (long long)p.first * b[x];
			ans += p.second;
			
			p = ta.query(y);
			ans += (long long)p.first * y;
			ans -= p.second;

			tb.erase(b[x]);
			tb.insert(y);
			b[x] = y;
		}
		cout << ans << endl;
	}


	return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxN = 4e5 + 10;
ll N[2], Q, a[2][maxN];
ll tot, T[maxN], x[maxN], y[maxN], c[maxN], sum[2][maxN], d[2][maxN];
int read(); void write(ll);
int lowbit(int x){return x & -x;};
void update1(int x, int v, int t){
	for(; x <= tot; x += lowbit(x)) d[t][x] += v;
}
void update2(int x, int v, int t){
	for(; x <= tot; x += lowbit(x)) sum[t][x] += v;
}
ll query1(int x, int t){
	ll ans = 0;
	for(; x; x -= lowbit(x)) ans += d[t][x];
	return ans;
}
ll query2(int x, int t){
	ll ans = 0;
	for(; x; x -= lowbit(x)) ans += sum[t][x];
	return ans;
}
int main(){
	N[0] = read(); N[1] = read(); Q = read();
	for(int i = 1; i <= Q; i++) T[i] = read() - 1, x[i] = read(), c[i] = y[i] = read();
	sort(c + 1, c + Q + 1);
	tot = unique(c + 1, c + Q + 1) - c;
	T[0] = 0; for(int i = 1; i <= N[0]; i++) update1(1, 1, 0);
	T[0] = 1; for(int i = 1; i <= N[1]; i++) update1(1, 1, 1);
	ll ans = 0;
	for(int i = 1; i <= Q; i++){
		int _new = lower_bound(c, c + tot, y[i]) - c;
		int _old = a[T[i]][x[i]] + 1; a[T[i]][x[i]] = _new++;
		int t = T[i] ^ 1;
		ans += query2(_old, t) - query1(_old, t) * c[_old - 1];
		ll x = query1(_new, t), y = query2(_new, t);
		ans += x * c[_new - 1] - y;
		write(ans); puts("");
		update1(_old, -1, T[i]); update1(_new, 1, T[i]);
		update2(_old, -c[_old - 1], T[i]); update2(_new, c[_new - 1], T[i]);
	}
	return 0;
}
int read(){
	int s = 0; char ch = getchar();
	while(!isdigit(ch)) ch = getchar();
	while(isdigit(ch)) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
	return s;
}
void write(ll x){
	if(x < 0) x = -x, putchar('-');
	if(x > 9) write(x / 10);
	putchar(x % 10 ^ 48);
}