sgu199:Beautiful People(最长上升子序列)

题意:

告诉你有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;	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值