hdu5406 CRB and Apple dp+两个LIS
题意转换为:给定n个数,求两个最长的不相交的LIS。
dp[i][j]表示当前两个LIS末尾为i和j时的dp值。(其实是 <= i和 <= j时的dp值)
dp[i][j] = max(dp[i][k])+1, k <= j;
我们只要先将答案存在一个数组里,然后统一更新dp数组的行值与列值即可。
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 using namespace std; 6 7 struct p{ 8 int h, d; 9 p(){} 10 p(int h, int d):h(h), d(d){} 11 bool operator <(const p& x) const{ 12 return h != x.h? h > x.h : d < x.d; 13 } 14 }; 15 p pp[1005]; 16 int s[2005]; 17 int dp[1005][1005], tmp[1005]; 18 19 void add(int* a, int x, int d){ 20 for(int i = x; i < 1005; i += i&-i) 21 a[i] = max(a[i], d); 22 } 23 int sum(int* a, int x){ 24 int ret = 0; 25 for(int i = x; i; i -= i&-i) 26 ret = max(ret, a[i]); 27 return ret; 28 } 29 30 int main(){ 31 int t, n; scanf("%d", &t); 32 while(t--){ 33 scanf("%d", &n); 34 for(int i = 0; i < n; i++){ 35 scanf("%d%d", &pp[i].h, &pp[i].d); 36 s[i] = pp[i].d; 37 } 38 sort(pp, pp+n); 39 sort(s, s+n); 40 for(int i = 0; i < n; i++) 41 pp[i].d = lower_bound(s, s+n, pp[i].d)-s+1; 42 43 memset(dp, 0, sizeof(dp)); 44 int ans = 0; 45 for(int i = 0; i < n; i++){ 46 int v = pp[i].d; 47 for(int j = 1; j <= n; j++){ 48 tmp[j] = sum(dp[j], v)+1; 49 ans = max(ans, tmp[j]); 50 } 51 for(int j = 1; j <= n; j++){ 52 add(dp[j], v, tmp[j]); 53 add(dp[v], j, tmp[j]); 54 } 55 } 56 printf("%d\n", ans); 57 } 58 return 0; 59 }
最优复杂度能做到nlogn,参考杨氏图表。
类似题
求两个不相交的上升子序列和下降子序列,使得序列长度之和最大
诸神对凡人心生艳羡,厌倦天堂。