http://acm.hdu.edu.cn/showproblem.php?pid=3525
原来只是在网上找线段树的,就找到这道题,LCS可以用线段树来优化,但实际上在这题中,将LCS转化为求最长上升子序列效率更高
#include <cstdio> #include <vector> #include <string> #include <algorithm> #include <queue> #include <cstring> #include <map> #include <set> #include <iostream> #include <cmath> using namespace std; const int MAXNM = 200005; int n, m; int data[2][MAXNM]; int bk[MAXNM][13]; int mmp[MAXNM*10]; int ttp[MAXNM*10]; int ba[MAXNM]; int next[MAXNM]; void solve(int dd[]) { memset(ba, 0, sizeof ba); for (int i = 1; i<= m*n; ++i) { bk[dd[i]][ba[dd[i]]++] = i; } } int mget(int a) { int i = a; while (next[i] != i) i = mget(next[i]); return next[a] = i; } void minit(int dd[]) { int a, b, c; for (int i = 0; i<= n*m*2; ++i) next[i] = i, dd[i] = 0; for (int i = 0; i< m*n; ++i) { scanf("%d%d", &a, &b); c = mget(b); dd[c] = a; next[c] = c+1; } a = b = 1; while (a <= n*m) { if (dd[b]) { dd[a] = dd[b]; ++a, ++b; } else ++b; } } // 最长上升子序列 int LCS(int len) { if (0 == len) return 0; int s = 1; ttp[0] = mmp[0]; for (int i = 1; i< len; ++i) { int ap = mmp[i]; int *id = (int *)lower_bound(ttp, ttp+s, ap); if (id == ttp+s) { ttp[s++] = ap; } else { *id = ap; } } return s; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int t; scanf("%d", &t); for (int p = 1; p<= t; ++p) { printf("Case #%d: ", p); scanf("%d%d", &n, &m); for (int i = 0; i< 2; ++i) minit(data[i]); solve(data[1]); int s = 0; for (int i = 1; i<= n*m; ++i) { int j = data[0][i]; for (int k = m-1; k>= 0; k--) { mmp[s++] = bk[j][k]; } } printf("%d\n", LCS(s)); } return 0; }