ACdream 1216 Beautiful People 二路最长上升子序列
2016-06-14 19:41
363 查看
题目描述:
DescriptionThe most prestigious sports club in one city has exactly N members. Each of its members is strong and beautiful. More precisely, i-th member of this club (members being numbered by the time they entered the club) has strength Si and beauty Bi. Since this is a very prestigious club, its members are very rich and therefore extraordinary people, so they often extremely hate each other. Strictly speaking, i-th member of the club Mr X hates j-th member of the club Mr Y if Si <= Sj and Bi >= Bj or if Si >= Sj and Bi <= Bj (if both properties of Mr X are greater then corresponding properties of Mr Y, he doesn’t even notice him, on the other hand, if both of his properties are less, he respects Mr Y very much).
To celebrate a new 2003 year, the administration of the club is planning to organize a party. However they are afraid that if two people who hate each other would simultaneouly attend the party, after a drink or two they would start a fight. So no two people who hate each other should be invited. On the other hand, to keep the club prestige at the apropriate level, administration wants to invite as many people as possible.
Being the only one among administration who is not afraid of touching a computer, you are to write a program which would find out whom to invite to the party.
Input
The first line of the input file contains integer N — the number of members of the club. ( 2 ≤ N ≤ 100 000). Next N lines contain two numbers each — S i and B i respectively ( 1 ≤ Si, Bi ≤ 109).
Output
On the first line of the output file print the maximum number of the people that can be invited to the party. On the second line output N integers — numbers of members to be invited in arbitrary order. If several solutions exist, output any one.
Sample Input
4 1 1 1 2 2 1 2 2
Sample Output
2 1 4
题目分析:
有n个人,他们分别有两个值a和b,创建一个序列x,保证 xai < xaj, xbi < xbj (i < j)。输出序列中最多的人数以及他们的序号。这题是一道最长上升子序列的题目(我没有看出来~~),将这些人按照a升序排列,若a相同,按b降序排列。(这样保证对b进行的运算是满足a的最长上升子序列 不然会造成b是递增的子序列,而a值相等,就不满足题意了)
然后就是对b进行LIS算法,二分(lower_bound)求位置,将最长的序列求出来,并记录他们的原序号。
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cstdlib> #include <algorithm> using namespace std; const int MAXN=100005; const int INF=0x3f3f3f3f; struct node { int a,b; int number; }; bool cmp(node x,node y) { if (x.a==y.a) { return x.b>y.b; } return x.a<y.a; } node seq[MAXN]; int dp[MAXN]; int mark[MAXN]; int n; int main() { while(scanf("%d",&n)!=-1) { for(int i=1; i<=n; i++) { scanf("%d%d",&seq[i].a,&seq[i].b); seq[i].number=i; } sort(seq+1,seq+n+1,cmp); memset(dp,INF,sizeof(dp)); int ans=0; int len=1; for(int i=1; i<=n; i++) { int k=lower_bound(dp+1,dp+1+n,seq[i].b)-dp; //二分法也可以实现 if (k==len) { len++; } dp[k]=seq[i].b; mark[i]=k;//mark值记录的是以他们为终点的子序列长度 ans=max(k,ans); } printf("%d\n",ans); // for(int i=1; i<=n; i++) // { // printf("%d ",mark[i]); // } // printf("\n"); for(int i=n; i>=1; i--) { if (mark[i]==ans) { printf("%d ",seq[i].number); ans--; } } printf("\n"); //这样输出的编号顺序是倒置的 不过因为题目允许,所以就这样了 如果要顺序输出编号,可以使用vector容器将这些人的编号存入 } return 0; }
附上LIS详解:
http://www.cnblogs.com/mycapple/archive/2012/08/22/2651461.html
相关文章推荐
- LIS算法: 最长上升子序列
- 使用java实现LIS算法,出操队形的问题
- Linux 的Ext2
- Linux Shell脚本攻略笔记4之让文本飞
- Linux Shell脚本攻略笔记3之以文件为名
- Linux 内核调试器内幕 —— KDB 入门指南
- Queueing in the Linux Network Stack !!!!!!!!!!!!!!!
- linux下syscall函数,SYS_gettid,SYS_tgkill
- CENTOS6.5彻底卸载MYSQL
- 2016 年最佳 Linux 图像管理软件
- docker的一些用法
- OpenStack 学习笔记(六):OpenStack neutron服务搭建
- 一张图看Goodle Clean设计架构
- h5网站和好看的动画网址
- centos防火墙关闭
- linux历史——正在更新中
- linux下用Apache一个IP多个网站多域名配置方法
- 一座逝去的里程碑VxWorks2Linux
- RHEL7下的Nginx的配置安装(一)
- Codeforces521D Shop