#include <iostream>
#include <vector>
#include <set>
using namespace std;
struct Node {
        int val;
        Node *left;
        Node *right;
        Node() {
               val = 0;
               left = NULL;
               right = NULL;
        }
};
string preorder(Node *root) {
        string ans = "";
        //V는 방문하지 않은 노드를 방문할 때 쓰는 check
        ans += "V";
        if (root->left) {
               //L은 left방문하지 않았을 때 방문하면서 ch
               ans += "L";
               ans += preorder(root->left);
               //l은 방문한 노드를 방문할 때 쓰는 ch
               ans += "l";
        }
        if (root->right) {
               ans += "R";
               ans += preorder(root->right);
               ans += "r";
        }
        //방문한 노드를 방문할때 쓰는 v
        ans += "v";
        return ans;
}
void remove(Node *root) {
        //root의 왼쪽자식이 있으면 그것부터 지우러간다.
        if (root->left) {
               remove(root->left);
        }
        if (root->right) {
               remove(root->right);
        }
        delete root;
}
int main(void) {
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        int n, m;
        cin >> n >> m;
        set<string> s;
        for (int k = 0; k < n; ++k) {
               vector<int> a(m);
               for (int i = 0; i < m; ++i) {
                       cin >> a[i];
               }
               Node *root = new Node;
               root->val = a[0];
               for (int i = 1; i < m; ++i) {
                       Node *cur = root;
                       while (true) {
                               // 비교하는 값보다 노드가 더 크면 왼쪽에 넣어야 한다.
                               if (cur->val > a[i]) {
                                      //왼쪽에 넣어야하는데 비었으면 그자리가 자기자리다.
                                      if (cur->left == NULL) {
                                              cur->left = new Node;
                                              cur->left->val = a[i];
                                              break;
                                      }
                                      //그렇지 않다면 왼쪽으로 계속 탐색한다.
                                      else {
                                              cur = cur->left;
                                      }
                               }
                               else if (cur->val < a[i]) {
                                      if (cur->right == NULL) {
                                              cur->right = new Node;
                                              cur->right->val = a[i];
                                              break;
                                      }
                                      else {
                                              cur = cur->right;
                                      }
                               }
                               else {
                                      break;
                               }
                       }
               }
               s.insert(preorder(root));
               remove(root);
        }
        cout << s.size() << '\n';
        return 0;
}

+ Recent posts