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++: #include <iostream>
#include <string.h>
using namespace std;

const int WIDTH = 5;
const int BLOCK_LENGTH_MAX = 5;

class Tetoris
{
public:
	Tetoris( int num ) :
		m_numBlocks( num ),
		m_pField( NULL ),
		m_heightMax( 0 ),
		m_cellCount( 0 )
	{
		memset( m_heights, 0, sizeof(m_heights) );
		m_pField = new bool[ num * BLOCK_LENGTH_MAX * WIDTH ]();
		m_pFullLine = new bool[ num * BLOCK_LENGTH_MAX ]();
	}
	~Tetoris()
	{
		delete[] m_pField;
		delete[] m_pFullLine;
	}
	void dropBlock( int direction, int length, int position )
	{
		m_cellCount += length;
		int h = 0;
		if( direction == 1 ){
			for( int i = 0; i < length; ++i ){
				if( h < m_heights[ i + position ] ) h = m_heights[ i + position ];
			}
			for( int i = 0; i < length; ++i ){
				m_pField[ h * WIDTH + i + position ] = true;
				m_heights[ i + position ] = h + 1;
			}
			if( isFilled( h ) ){
				m_pFullLine[ h ] = true;
			}
			detectHeights( m_heightMax + 1 );
		}else{
			h = m_heights[ position ];
			int up = 0;
			for( int i = 0; i < length; ++i ){
				while( m_pFullLine[ h + i + up ] ){
					++up;
				}
				m_pField[ ( h + i + up ) * WIDTH + position ] = true;
			}
			m_heights[ position ] += length + up;
			for( int i = 0; i < length + up; ++i ){
				if( isFilled( h + i ) ){
					m_pFullLine[ h + i ] = true;
				}
			}
			detectHeights( m_heightMax + length );
		}
	}
	bool isFilled( int h )
	{
		for( int i = 0; i < WIDTH; ++i ){
			if( !m_pField[ h * WIDTH + i ] ){
				return false;
			}
		}
		return true;
	}
	void detectHeights( int h )
	{
		m_heightMax = 0;
		for( int i = 0; i < WIDTH; ++i ){
			int p = h;
			while( p >= 0 && ( !m_pField[ p * WIDTH + i ] || m_pFullLine[ p ] ) ){
				--p;
			}
			p += 1;
			while( p < m_numBlocks * BLOCK_LENGTH_MAX && m_pField[ p * WIDTH + i ] ){
				++p;
			}
			m_heights[ i ] = p;
			if( m_heightMax < m_heights[ i ] ){
				m_heightMax = m_heights[ i ];
			}
		}
	}
	int getResult()
	{
		int countFilledLine = 0;
		for( int i = 0; i < m_heightMax; ++i ){
			if( m_pFullLine[ i ] ) ++countFilledLine;
		}
		return m_cellCount - countFilledLine * WIDTH;
	}
	void outputState()
	{
		for( int i = m_heightMax - 1; i >= 0; --i ){
			for( int j = 0; j < WIDTH; ++j ){
				cout << ( m_pField[ i * WIDTH + j ] ? 'o' : '.' );
			}
			cout << endl;
		}
		cout << "heights:" << endl;
		for( int i = 0; i < WIDTH; ++i ){
			cout << m_heights[ i ] << ' ';
		}
		cout << endl;
		cout << "heightMax : " << m_heightMax << endl << endl;
	}

private:
	int m_numBlocks;
	bool* m_pField;
	int m_heightMax;
	int m_heights[ WIDTH ];
	bool* m_pFullLine;
	int m_cellCount;
};

int main()
{
	int n;

	while( cin >> n && n )
	{
		Tetoris t( n );
		for( int i = 0; i < n; ++i ){
			int d, l, p;
			cin >> d >> l >> p;
			t.dropBlock( d, l, p - 1 );
			t.outputState();
		}
		cout << t.getResult() << endl;
	}

	return 0;
}

C++: #include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#ifdef _WIN32
#define __builtin_popcount __popcnt
#endif
int n, d, p, q;
int main() {
	while (cin >> n, n) {
		vector<int> bit;
		vector<int> c(5);
		while (n--) {
			cin >> d >> p >> q; q--;
			if (d == 1) {
				int r = *max_element(c.begin() + q, c.begin() + q + p);
				int b = (1 << (q + p)) - (1 << q);
				if (bit.size() == r) bit.push_back(b);
				else bit[r] |= b;
			}
			else {
				for (int i = c[q]; i < c[q] + p; i++) {
					if (bit.size() == i) bit.push_back(1 << q);
					else bit[i] |= 1 << q;
				}
			}
			vector<int> bit2;
			for (int i : bit) {
				if (i != 31) bit2.push_back(i);
			}
			bit = bit2;
			for (int i = 0; i < 5; i++) {
				c[i] = 0;
				for (int j = bit2.size() - 1; j >= 0; j--) {
					if (bit2[j] & (1 << i)) {
						c[i] = j + 1; break;
					}
				}
			}
		}
		int ret = 0;
		for (int i : bit) ret += __builtin_popcount(i);
		cout << ret << endl;
	}
	return 0;
}

C++: #include <iostream>
#include <vector>
#include <cstring>

using namespace std;

int n;

typedef struct Block
{
	int d;
	int p;
	int q;
} B;

int F[5005][5];
int H[5];

B blocks[1000];

int highest(int r, int l)
{
	int max = 0;
	for(int i=r; i<l; i++)
	{
		if(max < H[i])
		{
			max =H[i];
		}
	}
	return max;
}

void yoko_set(B b)
{
	int hp = highest(b.q, b.p+b.q);
	for(int i=b.q; i<b.p+b.q; i++)
	{
		F[hp][i] =1;
		H[i] = hp+1;
	}
}

void tate_set(B b)
{
	int hp = H[b.q];
	for(int i=hp; i<hp+b.p; i++)
	{
		F[i][b.q] = 1;
	}
	H[b.q] = hp+b.p;
}

void col_clear()
{
	
	int hp = highest(0, 5);
	bool is_ok = false;
	vector<int> cols;
	for(int i=0; i<=hp; i++)
	{
		is_ok =true;
		for(int j=0; j<5; j++)
		{
			if(F[i][j]==1) continue;
			is_ok = false;
			break;
		}
		
		if(is_ok)
		{
			cols.push_back(i);
		}
	}
	
	if(cols.empty()) return;
	
	int c = 0;
	for(int i=0; i<hp; i++)
	{
		if(cols[c]==i)
		{
			c++;
			continue;
		}
		
		for(int j=0; j<5; j++)
		{
			F[i-c][j] = F[i][j];
		}
	}
	
	for(int i=hp-cols.size(); i<hp; i++)
	{
		for(int j=0; j<5; j++)
		{
			F[i][j] = 0;
		}
	}
	
	for(int j=0; j<5; j++)
	{
		int max = -1;
		for(int i=0; i<hp; i++)
		{
			if(F[i][j]==1)
			{
				max = i;
			}
		}
		H[j] = max+1;
	}
}

void print()
{
	for(int i=0; i<10; i++)
	{
		for(int j=0; j<5; j++)
		{
			cout << F[9-i][j] << " ";
		}
		cout <<endl;
	}
	cout << endl;
}

int main()
{
	while(cin >> n, n)
	{
		for(int i=0; i<n; i++)
		{
			cin >> blocks[i].d;
			cin >> blocks[i].p;
			cin >> blocks[i].q;
			blocks[i].q--;
		}
		
		memset(&F[0][0], 0, sizeof(int)*25000);
		memset(&H[0], 0, sizeof(int)*5);
		
		for(int i=0; i<n; i++)
		{
			if(blocks[i].d == 2)
			{
				tate_set(blocks[i]);
			}
			else
			{
				yoko_set(blocks[i]);
			}
			
			col_clear();
			
			//print();
		}
		
		int hp = highest(0, 5);
		int c = 0;
		for(int i=0; i<hp; i++)
		{
			for(int j=0; j<5; j++)
			{
				if(F[i][j]==1) c++;
			}
		}
		cout << c<< endl;
	}
	
	return 0;
}