1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
struct Fenwick {
int n;
vector<int> bit;
Fenwick() : n(0) {}
explicit Fenwick(int n_) { init(n_); }
void init(int n_) {
n = n_;
bit.assign(n + 1, 0);
}
void update(int idx, int val) {
for (; idx <= n; idx += idx & -idx) bit[idx] = max(bit[idx], val);
}
int query(int idx) const {
int res = 0;
for (; idx > 0; idx -= idx & -idx) res = max(res, bit[idx]);
return res;
}
void clearIndex(int idx) {
for (int i = idx; i <= n; i += i & -i) bit[i] = 0;
}
};
struct Node {
int k; // rank in row1 (1..N)
int x; // rank in row2 (1..N)
int y; // rank in row3 (1..N), 0 if M=2
int dp; // LIS length ending here
};
int M, N;
void cdq_solve(vector<Node> &a, int l, int r, Fenwick &fw) {
if (l == r) return;
int mid = (l + r) >> 1;
cdq_solve(a, l, mid, fw);
vector<int> L, R;
L.reserve(mid - l + 1);
R.reserve(r - mid);
for (int i = l; i <= mid; ++i) L.push_back(i);
for (int i = mid + 1; i <= r; ++i) R.push_back(i);
auto by_x = [&](int i, int j) {
return a[i].x < a[j].x;
};
sort(L.begin(), L.end(), by_x);
sort(R.begin(), R.end(), by_x);
vector<int> updatedYs;
updatedYs.reserve(L.size());
int p = 0;
for (int idx : R) {
while (p < (int)L.size() && a[L[p]].x < a[idx].x) {
fw.update(a[L[p]].y, a[L[p]].dp);
updatedYs.push_back(a[L[p]].y);
++p;
}
int best = fw.query(a[idx].y - 1); // strict y_left < y_right
a[idx].dp = max(a[idx].dp, best + 1);
}
if (!updatedYs.empty()) {
sort(updatedYs.begin(), updatedYs.end());
updatedYs.erase(unique(updatedYs.begin(), updatedYs.end()), updatedYs.end());
for (int y : updatedYs) fw.clearIndex(y);
}
cdq_solve(a, mid + 1, r, fw);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
if (!(cin >> M >> N)) return 0;
vector<vector<int>> val(M, vector<int>(N));
for (int i = 0; i < M; ++i) {
for (int j = 0; j < N; ++j) cin >> val[i][j];
}
// ranks per row: 1..N (ascending by value)
vector<vector<int>> rankRow(M, vector<int>(N));
for (int i = 0; i < M; ++i) {
vector<int> idx(N);
iota(idx.begin(), idx.end(), 0);
sort(idx.begin(), idx.end(), [&](int a, int b) {
return val[i][a] < val[i][b];
});
for (int pos = 0; pos < N; ++pos) rankRow[i][idx[pos]] = pos + 1;
}
// order columns by rank of row1
vector<int> colByR1(N);
for (int col = 0; col < N; ++col) colByR1[rankRow[0][col] - 1] = col;
if (M == 2) {
vector<int> seq;
seq.reserve(N);
for (int k = 0; k < N; ++k) {
int col = colByR1[k];
seq.push_back(rankRow[1][col]);
}
vector<int> tails;
for (int x : seq) {
auto it = lower_bound(tails.begin(), tails.end(), x);
if (it == tails.end()) tails.push_back(x);
else *it = x;
}
cout << (int)tails.size() << '\n';
return 0;
}
vector<Node> nodes;
nodes.reserve(N);
for (int k = 0; k < N; ++k) {
int col = colByR1[k];
nodes.push_back(Node{ k + 1, rankRow[1][col], rankRow[2][col], 1 });
}
Fenwick fw(N);
cdq_solve(nodes, 0, N - 1, fw);
int ans = 0;
for (const auto &nd : nodes) ans = max(ans, nd.dp);
cout << ans << '\n';
return 0;
}
|