题目大意
- 有n个人的,每个人有一个si和bi,对于i和j来说,只有当si < sj && bi < bj ,或者 si > sj && bi > bj 时,二人才不会互相讨厌。
- 也就是说,只有两个人其中一方的s和b都小于另一方时,二人才不会互相讨厌。
- 求最多有多少人不会互相讨厌
分析
- 给n个人按s排序从小到大,若s相等则按b从大到小排序。
- 然后求b的最长上升子序列的长度ans即可
- 用O(nlogn)的算法
- 最后再按照ans构造路径
代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define INF 0x7fffffff
const int maxn = 1e5+10;
struct Node {
int s , b;
int id;
bool operator < (const Node &rhs) const {
return (s < rhs.s) || (s == rhs.s && b > rhs.b);
}
}node[maxn];
int dp[maxn];
int g[maxn];
int rel[maxn];
int main()
{
int t , n;
cin >> t;
while(t--)
{
cin >> n;
for(int i = 0; i < n; i++) {
cin >> node[i].s >> node[i].b;
node[i].id = i + 1;
}
sort(node , node + n);
for(int i = 1; i <= n; i++) g[i] = INF;
for(int i = 0; i < n; i++) {
int k = lower_bound(g+1 , g+1+n , node[i].b) - g;
dp[i] = k;
g[k] = node[i].b;
}
int ans = dp[0] , cnt = 0;;
for(int i = 1; i < n; i++) ans = max(ans , dp[i]);
cout << ans << endl;
for(int i = n-1; i >= 0; i--) if(ans == dp[i]) {
rel[cnt++] = node[i].id;
ans--;
}
for(int i = cnt - 1; i > 0; i--) cout << rel[i] << " ";
cout << rel[0] << endl;
}
return 0;
}