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;
}
题意:
一个俱乐部有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;
}
相关文章推荐
- OPENWRT入门之二------编译openwrt
- OPENWRT入门之一------openwrt简介
- shell 下执行mysql 命令
- [opencv] 摄像头操作
- 【Linux高频命令专题(15)】more
- 【Linux高频命令专题(14)】nl
- 鸟哥linux私房菜部分命令摘录(2)
- 网站运维常用小技巧,排错必备
- 鸟哥linux私房菜部分命令摘录(1)
- Centos下Yum安装PHP5.5,5.6
- linux系统下apt-get指令的使用
- OPENCV3.0 单目摄像头标定(使用官方自带的标定图片)
- *LeetCode-Copy List with Random Pointer
- SCrollTOP scrollHeight
- openswitch中的而一些命令
- 如何捕获 Linux 图形化登录界面的截图
- LFS 中文版手册发布:打造自己的 Linux 发行版
- 用PhotoShop制作透明背景图片
- 快速与MySQL交互,使用XMAPP打开MySQL数据库,并用shell进行与MySQL交互<Window 10>
- CentOS 7 配置squid 透明代理(测试笔记)