Problem:
Problem 03: Selecting Teams Advanced to Regional

日本で毎年開催される国際大学対抗プログラミングコンテストのアジア地区予選に出場するためには、厳しい国内予選を突破しなければなりません。

大学対抗とは言っても、１つの学校から複数のチームが参戦します。そこで、できるだけ多くの学校がアジア地区予選に出場できるように、突破チームの選抜には以下の選抜ルールが適用されます：

該当チームを A とし、成績の優秀な順番に次のルールを適用します：

ルール 1：

その時点での選抜チーム数が 10 に満たない場合：

A と同じ所属でその時点で選抜されたチームの数が 3 に満たなければ、A は選抜されます。

ルール 2：

その時点での選抜チーム数が 20 に満たない場合：

A と同じ所属でその時点で選抜されたチームの数が 2 に満たなければ、A は選抜されます。

ルール 3：

その時点での選抜チーム数が 26 に満たない場合：

A と同じ所属でその時点で選抜されたチームがなければ、A は選抜さます。

また、成績の順番は次のルールで決定されます：

より多くの問題を解いたチームが上位となります。

解いた問題数が同じ場合は、ペナルティが小さいチームが上位となります。

各チームのID（整数）、所属（整数）、正解数（整数）、ペナルティ（整数）を入力し、選抜チームのIDを選抜順に出力するプログラムを作成して下さい。
チームは成績順に与えられるとは限らないので、順位付けした後、選抜ルールを適用しなければならないことに注意して下さい。

この問題では、正解数とペナルティが同じチームがあった場合はIDが小さい方を上位とします。

Input

複数のデータセットが入力として与えられます。各データセットは以下の形式で与えられます：

n (チーム数：整数)

I1 U1 A1 P1 (1番目のチームのID、所属、正解数、ペナルティ：空白区切りの４つの整数)

I2 U2 A2 P2 (2番目のチームのID、所属、正解数、ペナルティ：空白区切りの４つの整数)

.

.

In Un An Pn (n番目のチームのID、所属、正解数、ペナルティ：空白区切りの４つの整数)

n は 300 以下であり、Ii, Ui は 1 以上 1000 以下とします。１つのデータセットに、同じ ID のチームは無いと仮定してかまいません。

Ai は 10 以下、Pi は 100,000 以下とします。

n が 0 のとき、入力の終わりとします。

Output

各データセットについて、選抜チームのIDを選抜された順に出力して下さい。1つのIDを1行に出力して下さい。

Sample Input

6
1 1 6 200
2 1 6 300
3 1 6 400
4 2 5 1200
5 1 5 1400
6 3 4 800
3
777 1 5 300
808 2 4 20
123 3 6 500
2
2 1 3 100
1 1 3 100
0

Output for the Sample Input

1
2
3
4
6
123
777
808
1
2

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;

namespace AOJ1043
{
    internal class Program
    {
        private static void Main()
        {
            foreach (var sortedTeams in from teams in ReadInputs()
                                        select from team in teams
                                               orderby team.Correct descending, team.Penalty, team.Id
                                               select team)
            {
                var picked = new List<Team>();
                foreach (var team in sortedTeams)
                {
                    var sameAffiliation = picked.Count(t => t.Affiliation == team.Affiliation);

                    if (picked.Count < 10)
                    {
                        if (sameAffiliation < 3)
                        {
                            picked.Add(team);
                        }
                    }
                    else if (picked.Count < 20)
                    {
                        if (sameAffiliation < 2)
                        {
                            picked.Add(team);
                        }
                    }
                    else if (picked.Count < 26)
                    {
                        if (sameAffiliation == 0)
                        {
                            picked.Add(team);
                        }
                    }
                }

                foreach (var team in picked)
                {
                    Console.WriteLine(team.Id);
                }
            }
        }

        public static IEnumerable<Team[]> ReadInputs()
        {
            while (true)
            {
                var count = int.Parse(Console.ReadLine() ?? "");
                if (count == 0) yield break;

                var teams = new Team[count];

                for (var i = 0; i < count; i++)
                {
                    var values = (Console.ReadLine() ?? "").Split(' ').Select(int.Parse).ToArray();
                    teams[i] = new Team(values[0], values[1], values[2], values[3]);
                }

                yield return teams;
            }
        }
    }

    public class Team
    {
        public int Id { get; private set; }
        public int Affiliation { get; private set; }
        public int Correct { get; private set; }
        public int Penalty { get; private set; }

        public Team(int id, int affiliation, int correct, int penalty)
        {
            Id = id;
            Affiliation = affiliation;
            Correct = correct;
            Penalty = penalty;
        }
    }
}