偏序集的两个定理:
定理1) 令(X,≤)是一个有限偏序集,并令r是其最大链的大小。则X可以被划分成r个但不能再少的反链。
其对偶定理称为Dilworth定理:
定理2) 令(X,≤)是一个有限偏序集,并令m是反链的最大的大小。则X可以被划分成m个但不能再少的链。
即:链的最少划分数=反链的最长长度
Problem: 3636
排序: 第一关键字升序, 第二关键字降序。之后按照第二关键字求最长非递增子序列的长度就是答案.
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1000000000
//typedef __int64 LL;
#define N 21111
int n, sta[N], tot;
struct node {
int w, h;
}p[N];
int cmp(node a, node b) {
if(a.w == b.w) return a.h > b.h;
return a.w < b.w;
}
int search(int x, int l , int r) {
int ret;
while(l <= r) {
int m = (l + r) >>1;
if(sta[m] < x) ret = m, r = m - 1;
else l = m + 1;
}
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
int t;
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 1;i <= n; i++) {
scanf("%d%d", &p[i].w, &p[i].h);
}
sort(p+1, p+1+n, cmp);
tot = 0;
for(int i = 1; i <= n; i++) {
int now = p[i].h;
if( tot == 0 || sta[tot] >= now) {
tot ++;
sta[tot] = now;
}
else {
int id = search(now, 1, tot);
sta[id] = now;
}
}
cout<<tot<<endl;
}
return 0;
}
Problem: 1065
排序:第一关键字升序,第二关键字也是升序。求排序后第二关键字的最长严格递减序列的长度即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1000000000
//typedef __int64 LL;
#define N 21111
int n, sta[N], tot;
struct node {
int w, h;
}p[N];
int cmp(node a, node b) {
if(a.w == b.w) return a.h < b.h;
return a.w < b.w;
}
int search(int x, int l , int r) {
int ret;
while(l <= r) {
int m = (l + r) >>1;
if(sta[m] <= x) ret = m, r = m - 1;
else l = m + 1;
}
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
int t;
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 1;i <= n; i++) {
scanf("%d%d", &p[i].w, &p[i].h);
}
sort(p+1, p+1+n, cmp);
tot = 0;
for(int i = 1; i <= n; i++) {
int now = p[i].h;
if( tot == 0 || sta[tot] > now) {
tot ++;
sta[tot] = now;
}
else {
int id = search(now, 1, tot);
sta[id] = now;
}
}
cout<<tot<<endl;
}
return 0;
}