Problem:
テトリス

テトリスは、落ちてくるブロックを盤面上に並べて消すゲームです。ここでは、それを少しアレンジしたゲームを考えましょう。

このゲームの盤面の大きさは横 5 コマで、出現するブロックがすべて入るだけの高さがあります。落ちてくるブロックは直線状で、横向き、縦向きの 2 種類があり、長さは 1 から 5 までの 5 種類です。

以下に例を示します。Step(イ) からStep(ホ)までの図はブロックが落ちて消えていく様子を表したものです。
Step(イ)から順にStep(ロ)、Step(ハ)と順に進んでいきます。

ブロックを落とすときに、Step(イ)のようにブロックのどこかが下に積んであるブロックに引っかかったときには、Step(ロ)のように落ちたブロックはその場所で止まります。また、ブロックを落とした結果、盤面の横一行の全てのコマにブロックが詰まった場合には、Step(ニ)で示されるように、その行のブロックが消えます。この後、消えた行の上にあるブロックが、そのままの形で1行下にしずみます(Step(ホ))。

1 ゲームは 1000 個以内のブロックが順に落ちてくることとします。例えば、落ちるブロックの長さが順番に横向き 4 コマ, 横向き 3 コマ, 縦向き 2 コマ, 縦向き 3 コマで、落ちる場所が左端から 1 コマ目、1 コマ目、4 コマ目、5 コマ目であった場合には、下図のStep(イ)~(ト)のように落ち、最後に残るブロックは 2 コマになります。

順番に落ちてくるブロックの情報を入力とし、全てのブロックが落ちた時に残るコマ数を出力するプログラムを作成してください。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロひとつの行で示されます。各データセットは以下の形式で与えられます。

n
d1 p1 q1
d2 p2 q2
:
dn pn qn

１行目にブロックの数 n (1 ≤ n ≤ 1000) が与えられます。続く n 行に i 個目のブロックの向き di (1 または2)、ブロックの長さ pi (1 ≤ pi ≤ 5)、ブロックの位置 qi が与えられます。ブロックの向き di は 1 が横向きを、2 が縦向きを表します。ブロックの位置 qi は盤面上の左端から1 ~ 5 までの整数とし、横向きのブロックの場合は左端のコマの落ちる位置とします。

データセットの数は 20 を超えません。

Output

データセット毎に最後に残るブロックの占めるコマ数を１行に出力します。

Sample Input

4
1 4 1
1 3 1
2 2 4
2 3 5
1
1 5 1
7
2 2 2
1 4 1
2 1 3
1 4 1
1 1 1
2 5 5
1 4 2
0

Output for the Sample Input

2
0
6

Solution in C++ (judge verdict: Accepted)

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <functional>
#include <iostream>
#include <iomanip>
#include <iterator>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <utility>
#include <vector>

using namespace std;

typedef long long Long;
#define Whole(xs) xs.begin(), xs.end()

template<class T>
ostream& operator<<(ostream& os, const vector<T>& vs) {
    if (vs.empty()) return os << "[]";
    os << "[" << vs[0];
    for (int i = 0; i < vs.size(); i++) os << " " << vs[i];
    return os << "]";
}
ostream& operator<<(ostream& os, const vector<int>& vs) {
    if (vs.empty()) return os << "[]";
    bool flag = false;
    os << "[";
    for (int i = 0; i < vs.size(); i++) {
        if (flag) {
            os << " ";
        } else {
            flag = true;
        }
        for (int j = 0; j < 5; j++) {
            os << ( (vs[i] & (1 << j)) > 0 );
        }
    }
    return os << "]";
}

const int IINF = 1<<28;
const Long LINF = 1LL<<56;
#define INF IINF

int N;
vector<int> F;
bool Input() {
    cin >> N;
    if (N == 0 || cin.eof()) return false;
    F.clear();
    return true;
}

void WSet(int Q, int P) {
    int R = 0;
    for (int i = Q; i < Q + P; i++) {
        R ^= (1 << i);
    }
    if (F.empty()) {
        F.push_back(R);
    } else{
        if ((F.back() & R) == 0) {
            for (int i = F.size() - 1; i >= -1; i--) {
                if ( i < 0 || (F[i] & R) > 0 ) {
                    F[i + 1] ^= R;
                    break;
                }
            }
        } else {
            F.push_back(R);
        }
    }
}

void HSet(int Q, int P) {   
    if (F.empty()) {
        for (int i = 0; i < P; i++) {
            F.push_back(1 << Q);
        }
        return;
    }
    int Rem = P;
    for (int i = F.size() - 1; i >= -1; i--) {
        if (i < 0 || F[i] & (1 << Q)) {
            for (int j = i + 1; Rem > 0 && j < F.size(); j++) {
                Rem--;
                F[j] ^= (1 << Q);
            }
            break;
        }
    }
    for (int i = 0; i < Rem; i++) {
        F.push_back(1 << Q);
    }
}

void Fall() {
    vector<int> nF;
    for (int i = 0; i < F.size(); i++) {
        if (F[i] != (1 << 5) - 1) {
            nF.push_back(F[i]);
        }
    }
    F = nF;
}

void Solve() {
    for (int n = 0; n < N; n++) {
        int D, P, Q; cin >> D >> P >> Q;
        Q--;
        if (D == 1) {
            WSet(Q, P);
        } else {
            HSet(Q, P);
        }
        Fall();
    }
    int Ans = 0;
    for (int i = 0; i < F.size(); i++) {
        for (int j = 0; j < 5; j++) {
            if (F[i] & (1 << j)) {
                Ans++;
            }
        }
    }
    cout << Ans << endl;
}

int main() {
    while (Input()) {
        Solve();
    }
    return 0;
}