Go: package main

import (
	"bufio"
	"os"
	"strconv"
	"strings"
	"fmt"
)

var scanner = bufio.NewScanner(os.Stdin)
var (
	dat = [5000][5]int{}
	m = [5]int{}
)

func main() {
	for scanner.Scan() {
		for i := range dat {
			for j := range dat[i] {
				dat[i][j] = 0
			}
		}
		for i := range m {
			m[i] = 0
		}
		n, _ := strconv.Atoi(scanner.Text())
		if n == 0 {
			break
		}
		count := 0
		for i := 0; i < n; i++ {
			scanner.Scan()
			buf := strings.Split(scanner.Text(), " ")
			d, _ := strconv.Atoi(buf[0])
			p, _ := strconv.Atoi(buf[1])
			q, _ := strconv.Atoi(buf[2])
			q--
			count += p
			if d == 2 {
				for j := 0; j < p; j++ {
					dat[m[q]][q] = 1
					ok := true
					for k := 0; k < 5; k++ {
						if dat[m[q]][k] == 0 {
							ok = false
						}
					}
					if ok {
						for k := 0; k < 5; k++ {
							dat[m[q]][k] = 0
							for l := m[q]; l < 4999; l++ {
								dat[l][k] = dat[l+1][k]
							}
							for l := 4999; l >= 0; l-- {
								if dat[l][k] != 0 {
									m[k] = l+1
									break
								}
								if l == 0 {
									m[k] = 0
								}
							}
						}
						count -= 5
					} else {
						m[q]++
					}
				}
			} else {
				h := 0
				for i := 0; i < p; i++ {
					h = max(h, m[i+q])
				}
				for i := 0; i < p; i++ {
					dat[h][i+q] = 1
				}
				for i := 0; i < p; i++ {
					m[i+q] = h+1
				}
				ok := true
				for j := 0; j < 5; j++ {
					if dat[h][j] == 0 {
						ok = false
					}
				}
				if ok {
					for j := 0; j < 5; j++ {
						dat[h][j] = 0
						for k := h; k < 4999; k++ {
							dat[k][j]=dat[k+1][j]
						}
						for k := 4999; k>= 0; k-- {
							if dat[k][j] != 0 {
								m[j]=k+1
								break
							}
							if k == 0 {
								m[j] = 0
							}
						}
					}
					count -= 5
				}
			}
		}
		fmt.Println(count)
	}
}

func max(a, b int) int {
	if a < b {
		return b
	}
	return a
}

C++: // * template

#include <bits/stdc++.h>
#ifdef LOCAL
#include "dump.hpp"
#else
#define dump(...)
#endif

using namespace std;

template<class T> inline void chmax(T &a, const T &b) { if(a < b) a = b; }
template<class T> inline void chmin(T &a, const T &b) { if(a > b) a = b; }

template<class T, class U> inline void fill_array(T &e, const U &v) { e = v; }
template<class T, class U, size_t s> inline void fill_array(T (&a)[s], const U &v) {for(auto&e:a)fill_array(e,v);}
template<class T, class U, size_t s> inline void fill_array(array<T, s> &a, const U &v) {for(auto&e:a)fill_array(e,v);}
template<class T, class U> inline void fill_array(vector<T> &a, const U &v) {for(auto&e:a)fill_array(e,v);}

struct range {
	typedef int Int;
	struct iter {
		Int i;
		const Int s;
		constexpr iter(const Int &i_, const Int &s_):i(i_), s(s_) {}
		constexpr bool operator!=(const iter &r) const { return s > 0 ? i < r.i : i > r.i; }
		constexpr const Int &operator*() const { return i; }
		iter &operator++() { i += s; return *this; }
	};
	const Int f, l, s;
	constexpr range(const Int &f_, const Int &l_, const Int &s_):f(f_), l(l_), s(s_) {}
	constexpr range(const Int &f_, const Int &l_):f(f_), l(l_), s(1) {}
	constexpr range(const Int &num):f(0), l(num), s(1) {}
	constexpr iter begin() const { return iter(f, s); }
	constexpr iter end() const { return iter(l, s); }
};

// * solve

constexpr int MAX_NUM_BLOCK = 1000;
constexpr int MAX_BLOCK_SIZE = 5;
constexpr int WIDTH = 5;

bool field[MAX_NUM_BLOCK * MAX_BLOCK_SIZE + 1][WIDTH];
int next_pos[WIDTH];

void drop_block() {
	static constexpr int dx[] = {0, 1, 0};
	static constexpr int dy[] = {0, 0, 1};

	int d, p, q;
	cin >> d >> p >> q;

	int x = q - 1;
	int y = (d == 1 ? *max_element(begin(next_pos) + x, begin(next_pos) + x + p) : next_pos[x]);

	for(int i : range(p)) {
		field[y][x] = true;
		chmax(next_pos[x], y + 1);

		x += dx[d];
		y += dy[d];
	}
}

int calc_score() {
	const int h = *max_element(begin(next_pos), end(next_pos));

	int res = 0;
	for(int i : range(h)) {
		const int cnt = count(begin(field[i]), end(field[i]), true);
		if(cnt < WIDTH) res += cnt;
	}

	return res;
}

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

	for(int n; cin >> n && n;) {
		memset(field, false, sizeof(field));
		memset(next_pos, 0, sizeof(next_pos));

		for(int i : range(n)) {
			drop_block();
		}

		cout << calc_score() << endl;
	}

	return EXIT_SUCCESS;
}

C++: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
const ld eps = 1e-9;

//// < "d:\d_download\visual studio 2015\projects\programing_contest_c++\debug\a.txt" > "d:\d_download\visual studio 2015\projects\programing_contest_c++\debug\b.txt"

int fall(vector<vector<int>>&field, vector<vector<int>>&pino,int l) {
	{

	}
	int y = 0;
	for ( y = 0; y < field.size() - pino.size(); ++y) {
		bool ok = true;
		for (int i = 0; i < pino.size(); ++i) {
			for (int j = 0; j < pino[i].size(); ++j) {
				if (pino[i][j]) {
					if (field[y + i+1][l + j])ok = false;
				}
			}
		}
		if (!ok||y+pino.size()-1==field.size()) {
			break;
		}
	}
	for (int i = 0; i < pino.size(); ++i) {
		for (int j = 0; j < pino[i].size(); ++j) {
			if (pino[i][j]) {
				assert(!field[y + i][l + j]);
				field[y + i][l + j] = true;
			}
		}
	}
	int delline = 0;
	for (int i = y + pino.size() - 1; i >= y; --i) {
		if (all_of(field[i].begin(), field[i].end(), [](const int a) {return a == 1; })) {
			transform(field[i].begin(), field[i].end(), field[i].begin(), [](const int a) {return false; });
			for (int j = i- 1; j >= 0; --j) {
				swap(field[j], field[j + 1]);
			}
			delline += 1;
		}
	}
	return delline;
}

int main() {
	while (1) {
		int N; cin >> N;
		if (!N)break;
		int sum = 0;
		vector<vector<int>>field(5*N+10, vector<int>(5));
		for (int i = 0; i < N; ++i) {
			int d, p, q; cin >> d >> p >> q; q--;
			int w = d == 2 ? 1 : p;
			int h = d == 1 ? 1 : p;
			sum += p;
			vector<vector<int>>pino(h, vector<int>(w, 1));
			sum -= fall(field, pino, q) * 5;
		}
		cout << sum << endl;
	}
	
	return 0;
}

C++: #include<cstdio>
#include<vector>

#define	pb	push_back

using namespace std;

typedef	vector<int>	vi;

char field[5000];

bool vanish(int u,int l){
	vi rem;
	for(int i=l;i>=u;i--){
		if(field[i]!=31)	rem.pb(i);
	}

	int rnum=rem.size(),h=l-u+1;
	if(rnum!=l){
		for(int i=0;i<rnum;i++)	field[l-i]=field[rem[i]];
		for(int i=u-1;i>=0;i--)	field[h-rnum+i]=field[i];
		for(int i=0;i<rnum;i++)	field[i]=0;
	}
}

int main(){
	for(int n;scanf("%d",&n),n;){
		for(int i=0;i<5000;i++)	field[i]=0;
		for(int t=0;t<n;t++){
			int type,len,p;	scanf("%d%d%d",&type,&len,&p);
			p--;

			char blk;
			if(type==1)	blk=((1<<len)-1)<<(5-p-len);
			else		blk=1<<(4-p);

			for(int i=0;i<=5000;i++){
				if(i==5000 || (field[i]&blk)!=0){
					if(type==1){
						field[i-1]|=blk;
						vanish(i-1,i-1);
					}
					else{
						for(int j=1;j<=len;j++)	field[i-j]|=blk;
						vanish(i-len,i-1);
					}
					break;
				}
			}
		}

		int cnt=0;
		for(int i=0;i<5000;i++){
			for(int j=0;j<5;j++)	if(field[i]&(1<<j))	cnt++;
		}
		printf("%d\n",cnt);
	}

	return 0;
}