首页 > 技术文章 > hdu5406 CRB and Apple dp+两个LIS

dirge 2016-07-02 23:33 原文

题意转换为:给定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 }
View Code

 最优复杂度能做到nlogn,参考杨氏图表。

 

类似题

求两个不相交的上升子序列和下降子序列,使得序列长度之和最大

http://hihocoder.com/problemset/problem/1918

推荐阅读