Problem:
Problem F:
Alien Pianist
One day an alien came from some star far away in the universe. He was interested in cultures on the earth,
especially music. He enjoyed listening various kinds of music, and then he decided to play music by himself.
Fortunately, he met a composer in a concert and became a friend with him. He requested the composer to make
new pieces of music for him. The composer readily accepted the request.
The composer tried to make music, but has been bothered because the alien’s body is very different from those
of human beings. Music he can play is limited by the structure of his body. He has only one hand with many
fingers. He can stretch his fingers infinitely but he cannot cross his fingers. He was also requested to compose for
a special instrument called a
space piano
in his space ship. The piano has 2
31
keys numbered from 0 to 2
31
- 1
beginning at the left. The alien wanted to play the music with that piano.
The composer asked you, as a brilliant programmer, for help. Your job is to write a program to determine whether
the alien can play given pieces of music.
A piece of music consists of a sequence of notes and a note is a set of scales. He uses one finger for each scale
in a note. In order to play the music seamlessly, he must put fingers on all the keys of two adjacent notes for a
certain period of time. Of course he cannot cross fingers during that period.
For example, let us consider him playing a note {2, 4, 7} followed by a note {3, 6, 8}. If he plays the former note
by the third, the fifth and the eighth fingers (for 2, 4 and 7 respectively), then he can play the latter note by the
fourth, the sixth (or the seventh) and the ninth (or latter) fingers (for 3, 6 and 8 respectively).
Input
The input file contains several test cases.
The first line of each test case contains two integers: the number
N
of the alien’s fingers and the number
M
(0 <
M
≤ 1000) of notes in the score. Each of the following M lines represents a note; the first integer
L
i
(0 <
L
i
≤ 100) denotes the number of the scales it contains, and each of the following
L
i
integers denotes a scale.
Notes are ordered in terms of time. You can assume that the same scale doesn’t appear in any two adjacent notes.
The input file ends with a line containing two zeroes.
Output
For each test case, print a line containing the case number (beginning at 1) and the result. If the alien can play
the piece of music, print “Yes”. Otherwise, print “No”.
Sample Input
10 2
3 2 4 7
3 3 6 8
5 8
1 0
1 1
1 2
1 3
1 4
1 5
1 6
1 7
0 0
Output for the Sample Input
Case 1: Yes
Case 2: No

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

/* вершина аккорда */
struct Node {
    int key;          // номер клавиши
    int note;         // номер ноты
    vector<int> out;  // исходящие рёбра
};

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

    int N, M;                      // пальцы, кол-во нот
    for (int tc = 1; cin >> N >> M, N || M; ++tc) {

        vector<vector<int>> noteKeys(M);          // сами клавиши
        size_t total = 0;
        for (int i = 0, L; i < M; ++i) {
            cin >> L;
            noteKeys[i].resize(L);
            for (int &x : noteKeys[i]) cin >> x;
            sort(noteKeys[i].begin(), noteKeys[i].end());
            total += L;
        }

        /* --- создаём вершины --- */
        vector<Node> V;
        V.reserve(total);
        vector<vector<int>> noteIdx(M);           // индексы вершин каждой ноты

        for (int i = 0; i < M; ++i) {
            for (int key : noteKeys[i]) {
                noteIdx[i].push_back(V.size());
                V.push_back({key, i, {}});
            }
        }

        /* --- рёбра внутри одной ноты --- */
        for (int i = 0; i < M; ++i) {
            auto &idx = noteIdx[i];
            for (size_t k = 1; k < idx.size(); ++k)
                V[idx[k - 1]].out.push_back(idx[k]);
        }

        /* --- рёбра между соседними нотами --- */
        for (int i = 0; i + 1 < M; ++i) {
            auto &A = noteIdx[i];
            auto &B = noteIdx[i + 1];
            size_t p = 0, q = 0;
            vector<int> merged; merged.reserve(A.size() + B.size());
            while (p < A.size() || q < B.size()) {
                if (q == B.size() ||
                    (p < A.size() && V[A[p]].key < V[B[q]].key))
                    merged.push_back(A[p++]);
                else
                    merged.push_back(B[q++]);
            }
            for (size_t k = 1; k < merged.size(); ++k)
                if (V[merged[k - 1]].note != V[merged[k]].note)
                    V[merged[k - 1]].out.push_back(merged[k]);
        }

        /* --- топологическая сортировка и поиск max path --- */
        vector<int> indeg(V.size()), dp(V.size(), 1);
        for (auto &n : V)
            for (int v : n.out) ++indeg[v];

        queue<int> q;
        for (size_t i = 0; i < V.size(); ++i)
            if (!indeg[i]) q.push(i);

        int best = 0;
        while (!q.empty()) {
            int u = q.front(); q.pop();
            best = max(best, dp[u]);
            for (int v : V[u].out) {
                dp[v] = max(dp[v], dp[u] + 1);
                if (!--indeg[v]) q.push(v);
            }
        }

        cout << "Case " << tc << ": " << (best <= N ? "Yes" : "No") << '\n';
    }
}
accuracy: 1
time_ms: 80
memory_kb: 11460
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct Vertex{
    int pitch;          // высота (тон)
    int note;           // номер ноты, в которой встречается
    vector<int> next;   // рёбра (макс 3)
};

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

    int N,M,  tc=0;
    while (cin>>N>>M, N||M){
        ++tc;
        vector<Vertex> v;             // все вершины подряд
        vector<int> start;            // start[i] – id первой вершины ноты i
        start.reserve(M);

        /* ---------- читаем все ноты и ставим внутрисловные рёбра --------- */
        for(int i=0;i<M;++i){
            int L;  cin>>L;
            vector<int> a(L);
            for(int &x:a) cin>>x;
            sort(a.begin(),a.end());

            start.push_back((int)v.size());
            for(int j=0;j<L;++j){
                v.push_back({a[j], i, {}});
                if(j)            // ребро внутри ноты
                    v[v.size()-2].next.push_back(v.size()-1);
            }
        }
        int V = (int)v.size();

        /* ------- рёбра между соседними нотами (одновременная игра) ------- */
        for(int i=0;i<M-1;++i){
            int p1 = start[i],           p2 = start[i+1];
            int e1 = (i+1==M?V:start[i+1]), e2 = (i+2==M?V:start[i+2]); // end ptr

            int i1=p1, i2=p2, last=-1;
            while(i1<e1 || i2<e2){
                int cur;
                if(i2==e2 || (i1<e1 && v[i1].pitch < v[i2].pitch)){
                    cur = i1++;               // берем из первой ноты
                }else{
                    cur = i2++;               // берём из второй
                }
                if(last!=-1 && v[last].note!=v[cur].note)
                    v[last].next.push_back(cur);   // граница блоков
                last = cur;
            }
        }

        /* ------------------ топологическая динамика ---------------------- */
        vector<int> order(V);
        iota(order.begin(), order.end(), 0);
        sort(order.begin(), order.end(),
             [&](int a,int b){ return v[a].pitch < v[b].pitch; });

        vector<int> dp(V,1);
        int L = 1;
        for(int id: order){
            for(int to: v[id].next){
                if(dp[to] < dp[id]+1){
                    dp[to] = dp[id]+1;
                }
            }
            L = max(L, dp[id]);
        }

        cout<<"Case "<<tc<<": "<<(L<=N ? "Yes":"No")<<"\n";
    }
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 10828
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct Node {
    int key;           // номер клавиши
    int nxt[3];        // максимум 3 дуги
    int deg = 0;       // их количество
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N, M, tc = 1;
    while (cin >> N >> M, N || M) {
        vector<int> sz(M);            // L_i
        vector<int> start(M);         // позиция 1-й клавиши ноты i
        vector<Node> g;               // все «нажатия»

        /* --- читаем партитуру --- */
        for (int i = 0; i < M; ++i) {
            cin >> sz[i];
            if (i) start[i] = start[i - 1] + sz[i - 1];
            vector<int> v(sz[i]);
            for (int &x : v) cin >> x;
            sort(v.begin(), v.end());            // порядок слева-направо
            for (int x : v) g.push_back({x});    // создаём узел
        }

        /* --- дуги внутри одной ноты --- */
        for (int i = 0; i < M; ++i)
            for (int j = 0; j + 1 < sz[i]; ++j) {
                int u = start[i] + j;
                g[u].nxt[g[u].deg++] = u + 1;
            }

        /* --- дуги между соседними нотами --- */
        for (int i = 1; i < M; ++i) {
            int h1 = 0, h2 = 0;
            while (h1 < sz[i - 1] && h2 < sz[i]) {
                int u = start[i - 1] + h1;
                int v = start[i]     + h2;
                int u0 = u, v0 = v;

                while (h1 < sz[i - 1] && g[u].key < g[v].key) { ++h1; ++u; }
                if (u != u0) g[u - 1].nxt[g[u - 1].deg++] = v;

                while (h2 < sz[i] && g[v].key < g[u].key) { ++h2; ++v; }
                if (v != v0) g[v - 1].nxt[g[v - 1].deg++] = u;
            }
        }

        /* --- поиск длины наибольшего пути в DAG --- */
        int V = g.size();
        vector<int> dp(V, -1);
        function<int(int)> dfs = [&](int v) -> int {
            int &res = dp[v];
            if (res != -1) return res;
            res = 1;
            for (int k = 0; k < g[v].deg; ++k)
                res = max(res, dfs(g[v].nxt[k]) + 1);
            return res;
        };

        int longest = 0;
        for (int i = 0; i < V && longest <= N; ++i)
            longest = max(longest, dfs(i));

        cout << "Case " << tc++ << ": " << (longest <= N ? "Yes" : "No") << '\n';
    }
}
accuracy: 1
time_ms: 50
memory_kb: 14280
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

// We will build a DAG on all "notes×scales" nodes.
//   – Within each note i, its scales sorted: we link k→k+1.
//   – Between adjacent notes i and i+1, we merge the two sorted lists
//     and link every consecutive pair in the merged order.
//
// Then we compute the length of the longest path in this DAG.
// If it exceeds N, we must use >N distinct fingers in one chain ⇒ NO.
// Otherwise YES.

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

    int N, M, tc=1;
    while(cin>>N>>M){
        if(N==0 && M==0) break;

        vector<vector<int>> notes(M);
        vector<int> L(M);
        for(int i=0;i<M;i++){
            cin>>L[i];
            notes[i].resize(L[i]);
            for(int j=0;j<L[i];j++){
                cin>>notes[i][j];
            }
            sort(notes[i].begin(), notes[i].end());
        }

        // Number all nodes 0..T-1
        // node_id[i][k] = unique id for the k-th scale in note i
        vector<vector<int>> node_id(M);
        int T=0;
        for(int i=0;i<M;i++){
            node_id[i].resize(L[i]);
            for(int k=0;k<L[i];k++){
                node_id[i][k]=T++;
            }
        }

        vector<vector<int>> adj(T);
        vector<int> indeg(T,0);

        // 1) Within each note: chain k->k+1
        for(int i=0;i<M;i++){
            for(int k=0;k+1<L[i];k++){
                int u=node_id[i][k], v=node_id[i][k+1];
                adj[u].push_back(v);
                indeg[v]++;
            }
        }

        // 2) Between adjacent notes: merge and chain
        for(int i=0;i+1<M;i++){
            auto &A=notes[i];
            auto &B=notes[i+1];
            int a=0,b=0;
            vector<pair<int,int>> merged; // (key, node_id)
            merged.reserve(L[i]+L[i+1]);
            while(a<L[i]||b<L[i+1]){
                if(b>=L[i+1] || (a<L[i] && A[a]<B[b])){
                    merged.emplace_back(A[a], node_id[i][a]);
                    a++;
                } else {
                    merged.emplace_back(B[b], node_id[i+1][b]);
                    b++;
                }
            }
            for(int j=0;j+1<(int)merged.size();j++){
                int u=merged[j].second, v=merged[j+1].second;
                adj[u].push_back(v);
                indeg[v]++;
            }
        }

        // 3) Topo DP for longest path
        queue<int> q;
        vector<int> dp(T,0);
        int best=0;
        for(int u=0;u<T;u++){
            if(indeg[u]==0){
                q.push(u);
                dp[u]=1;          // chain of length 1 (itself)
                best = max(best, dp[u]);
            }
        }
        int seen=0;
        while(!q.empty()){
            int u=q.front();q.pop();
            seen++;
            for(int v: adj[u]){
                dp[v] = max(dp[v], dp[u]+1);
                best = max(best, dp[v]);
                if(--indeg[v]==0){
                    q.push(v);
                }
            }
        }
        // If seen<T, there's a cycle—but by construction there cannot be one.

        cout<<"Case "<<tc++<<": "<<(best<=N?"Yes":"No")<<"\n";
    }
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 10452
final_rank: 1