题意:
告诉你有n个人,以及每个人的力量和美丽的程度值(我记录为x,y),并依次记录他们的id为1~n。用两个人(i和j)比较,p[i].x > p[j].x && p[i].y> p[j].y 和 p[i].x < p[j].x && p[i].y < p[j].y 说明同时邀请这两人,他们就不会闹事,其余情况(p[i].x <= p[j].x && p[i].y >= p[j].y 和 p[i].x >=
p[j].x && p[i].y <= p[j].y)说明同时邀请他们就会出事,问最多可以邀请多少人,并且保证这些人不会闹事?
数据范围:2<=n<=10,000;1<=x,y<= 10^9;
分析:
按s为第一关键字,b为第二关键字,s递增,b递减,排序后, 做nlogn的最长上升子序列就好。
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 100009;
int n;
struct people
{
int s, b, i;
void read() {scanf("%d%d", &s, &b);}
}inv[MAXN];
int minf[MAXN];
int f[MAXN], pre[MAXN];
int ans, MAX;
int out[MAXN], top;
bool cmp(const people a, const people b) {return a.s<b.s || (a.s==b.s && a.b>b.b);}
int binary(int lim)
{
int l = 0, r = MAX;
while(l < r)
{
int mid = (l+r)>>1;
if(inv[minf[mid]].b < lim && inv[minf[mid+1]].b >= lim) return minf[mid];
else if(inv[minf[mid]].b < lim) l = mid+1;
else r = mid;
}
return minf[l];
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
{
inv[i].read();
inv[i].i = i;
}
sort(inv+1, inv+n+1, cmp);
for(int i = 1; i <= n; ++i)
{
int k = binary(inv[i].b);
pre[i] = k;
f[i] = f[k]+1;
if(f[i] > MAX) {MAX = f[i];ans = i;}
if(!minf[f[i]] || inv[minf[f[i]]].b > inv[i].b) minf[f[i]] = i;
}
printf("%d\n", MAX);
for(int i = ans; i; i = pre[i])
out[++top] = inv[i].i;
sort(out+1, out+top+1);
printf("%d", out[1]);
for(int i = 2; i <= top; ++i)
printf(" %d", out[i]);
printf("\n");
return 0;
}