您的位置:首页 > 运维架构

acdream 1426 Beautiful People(双线最长单调子序列)

2015-10-07 10:50 330 查看
题目链接:http://acdream.info/problem?pid=1216

题意:

一个俱乐部有n个人, 每个人都有一个漂亮值和财富值。现在俱乐部要举办活动, 但是俱乐部中有些人是相互讨厌, 相互讨厌的人有两累即si<=sj&&bi>=bj or si>=sj&&bi<=bj ;参加活动的人不能相互讨厌。 问最多能有多少人参加活动, 并把参加活动的人输出来。

分析:

很明显, 满足条件的人si, bi都是严格的单调的。 所以我们可以想到最长单调子序列, 这个就是多了一个条件的限制。我们可以先一个限制条件si从小到大排, 相同的bi一从大到小排;这样我们就可以按另一个限制条件bi求最长单调递增, 最后打印路径。相信有很多人不明白另一个限制条件bi要按从大到小排。我给出一个样例看了之后想想就明白了, 这里太不好描述了。

9

1 3

2 5

4 1

4 2

4 3

4 4

5 5 

6 6

最长长度为3,

AC代码:

#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cctype>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
int dp[maxn];
int x[maxn];
struct Info
{
int x, y, id;
bool operator < (const Info& rhs) const
{
if(x == rhs.x)
return y > rhs.y;
return x < rhs.x;
}
} a[maxn];
int search_id(int k, int len)
{
int l = 0, r = len, m;
while(l < r)
{
m = (l + r)/2;
if(k == x[m])
return m;
else if(k < x[m])
r = m;
else
l = m + 1;
}
return l;
}
int main()
{
int n, len = 0;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%d%d", &a[i].y, &a[i].x);
a[i].id = i+1;
}
sort(a, a+n);
a
.x = a
.y = inf;
x[len++] = a[0].y;
for(int i = 1; i < n; i++)
{
x[len] = inf;
int j = search_id(a[i].y, len);
if(j == len)
len++;
x[j] = a[i].y;
dp[i] = j;
}
printf("%d\n", len);
int ok = 1, j = n, k = len-1;
for(int i = n-1; i >= 0; i--)
{
if(k>=0 && dp[i]==k && a[i].x<a[j].x && a[i].y<a[j].y)
{
k--;
j = i;
if(ok == 1)
{
printf("%d", a[i].id);
ok = 0;
}
else
printf(" %d", a[i].id);
}
}
puts("");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: