题意:给定n个木棍的l和w,第一个木棍需要1min安装时间,若木棍(l’,w’)满足l' >= l, w' >= w,则不需要花费额外的安装时间,否则需要花费1min安装时间,求安装n个木棍的最少时间。
分析:
1、将木棍按l排序后,实质上是求按w形成的序列中的最长递减子序列。
eg:
5
4 9 5 2 2 1 3 5 1 4
将木棍按l排序后,按w形成的序列为4 1 5 9 2, 则若按照4 5 9 1 2的顺序安装(按照木棍标号为1 3 4 2 5的顺序安装),只需两分钟。
容易发现,所需时间为上升子序列的个数,根据Dilworth定理,最少的chain个数等于最大的antichain的大小,即最少上升子序列的个数等于最长递减子序列的长度。
2、按上例,最后求得dp数组中是单减序列,为9,2,-1,……,可见最少上升子序列的个数等于最长递减子序列的长度。
3、注意使用lower_bound()时从大到小排序后的greater<int>()。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<stack> #include<deque> #include<queue> #include<list> #define lowbit(x) (x & (-x)) const double eps = 1e-8; inline int dcmp(double a, double b){ if(fabs(a - b) < eps) return 0; return a > b ? 1 : -1; } typedef long long LL; typedef unsigned long long ULL; const int INT_INF = 0x3f3f3f3f; const int INT_M_INF = 0x7f7f7f7f; const LL LL_INF = 0x3f3f3f3f3f3f3f3f; const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f; const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; const int MOD = 1e9 + 7; const double pi = acos(-1.0); const int MAXN = 5000 + 10; const int MAXT = 10000 + 10; using namespace std; struct Node{ int l, w; void read(){ scanf("%d%d", &l, &w); } bool operator < (const Node& rhs)const{ return l < rhs.l || (l == rhs.l && w < rhs.w); } }num[MAXN]; int dp[MAXN]; int main(){ int T; scanf("%d", &T); while(T--){ int n; scanf("%d", &n); for(int i = 0; i < n; ++i){ num[i].read(); } sort(num, num + n); memset(dp, -1, sizeof dp); for(int i = 0; i < n; ++i){ for(int j = 0; j < n; ++j){ if(j == 0 || dp[j - 1] > num[i].w){ dp[j] = max(dp[j], num[i].w); } } } printf("%d ", lower_bound(dp, dp + n, -1, greater<int>()) - dp); } return 0; }