AC_Dream 1216 G - Beautiful People

题意:
有n个人每人有一个力气值Si,美丽值Bi,满足Bi>Bj&&Si>Sj 或者 Bi<Bj&&Si<Sj 的人可以
一起参见晚会,问最多有多少人可以一起参见晚会。
思路: 我们根据S从小到大将所有人排序,然后看B最长的上升子序列的长度求出来即可!
在排序中优先对S排序,S相等的则对B进行由大到小的排序,why?
也就是对于S相同的,我们先选取B最大的值插入LIS中,因为比如 S1=1, B1 = 1
S1=1, B1 = 2, S1=1, B1 = 3, 如果不进行排序,直接按照求B中的lis,显然长度
为3,显然是不对的,因为相同的S中只能选择一个B出来!所以就要对S相同的B进行
降序排序! 这样就变成了一个裸lis!

 1 #include<iostream>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cstdio>
 6 #define N 100005
 7 using namespace std;
 8
 9 struct node{
10     int x, y;
11     int p;
12 };
13
14 bool cmp(node a, node b){
15     if(a.x == b.x)
16            return a.y > b.y;
17     return a.x < b.x;
18 }
19
20 bool myCmp(node a, node b){
21     return a.y <= b.y;//这里要写成 <=;因为upper_bound返回的是“元素值 >插入值”
22                       //最后一个插入值的位置,元素值 == 插入值的时候,默认 元素值
23                       // >插入值,但在该题中,相等的情况下不能算在lis中的!
24 }
25
26 node a[N];
27 node c[N];
28
29 int pre[N], path[N];
30
31 int main(){
32     int n;
33     while(scanf("%d", &n) != EOF){
34         for(int i=0; i<n; ++i)
35             scanf("%d%d", &a[i].x, &a[i].y), a[i].p = i+1;
36
37         sort(a, a+n, cmp);
38         c[0] = a[0];
39         pre[0] = 0;
40         path[0] = 0;
41         int len = 1;
42
43         for(int i=1; i<n; ++i){
44             int k = upper_bound(c, c+len, a[i], myCmp) - c;
45             pre[i] = k ? path[k-1] : 0;//当前插入节点i的位置为k,它的前一个(k-1位置)元素的序号!
46             path[k] = i;//当前插入k位置的节点的序号
47             c[k] = a[i];
48             if(k+1 > len) len = k+1;
49         }
50         int tmp = path[len-1];
51         printf("%d\n", len);
52         printf("%d", a[path[len-1]].p);
53         for(int i=len-2; i >= 0; --i){
54             tmp = pre[tmp];
55             printf(" %d", a[tmp].p);
56         }
57         printf("\n");
58
59     }
60     return 0;
61 }

时间: 2024-12-13 10:09:36

AC_Dream 1216 G - Beautiful People的相关文章

ASC1 G Beautiful People

题意:给你一个二元组,求这个二元组的最长上升子序列,并且记录路径 解题思路:一个值从小到大排序,在这个值相等的情况情况下按从大到小排序(为了不取到第一个值相等),然后对第二个值 求一个最长上升自诩,路径的话求实求最长上升子序列的时候 记录 来自前一个值. 解题代码: 1 // File Name: e.cpp 2 // Author: darkdream 3 // Created Time: 2015年03月21日 星期六 19时58分58秒 4 5 #include<vector> 6 #i

ASC(1)G(最长上升子序列)

G - Beautiful People Time Limit: 10000/5000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)     Special Judge SubmitStatus Problem Description The most prestigious sports club in one city has exactly N members. Each of its members is stron

ASC(1)G(上升时间最长的序列)

G - Beautiful People Time Limit: 10000/5000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)     Special Judge SubmitStatus Problem Description The most prestigious sports club in one city has exactly N members. Each of its members is stron

建模美赛模板

1 \documentclass[12pt,a4paper,titlepage]{article} 2 3 \setlength{\textheight}{22.5true cm} 4 \setlength{\textwidth}{16.5true cm} \oddsidemargin -1pt 5 \evensidemargin -1pt \topmargin -1cm \setlength{\parskip}{0pt} 6 7 \usepackage{amsmath} 8 \usepacka

程序员是否必须会算法

本章的标题既然是"程序员与算法",就必然要涉及一个基本问题,那就是"程序员是否必须会算法".这是一个充满争议的问题,虽然并不像"生存还是毁灭"之类的选择那样艰难而沉重,但也绝不是一个轻松的话题.朋友们在我的"算法系列"博客专栏上发表的评论和回复,并不都是我所期待的赞美和鼓励,也常常会有一些冷言冷语.比如,"穷举也算是算法吗"或者"请你说明一下算法在XX系统中能起到什么作用". 有一次,一

[转] Python内存管理机制

转自:https://www.cnblogs.com/51try-again/p/11099999.html 一.引用计数 1.变量与对象 变量赋值的时候才创建,它可以指向(引用)任何类型的对象 python里每一个东西都是对象,它们的核心就是一个结构体:PyObject 变量必须先赋值,再引用. 比如,你定义一个计数器,你必须初始化成0,然后才能自增. 每个对象都包含两个头部字段(类型标识符和引用计数器) 关系图如下: 变量名没有类型,类型属于对象(因为变量引用对象,所以类型随对象),在Pyt

acd - 1216 - Beautiful People(二维LIS)

题意:一个人有两个属性S, B(1 ≤ Si, Bi ≤ 10^9),当两个人的这两个属性满足 S1 < S2 && B1 < B2 或者 S1 > S2 && B1 > B2 时,这两个人不会讨厌对方.现给出 N 个人(2 ≤ N ≤ 100 000)的属性,求最多能有多少个人,他们之间任意两人都不会讨厌对方. 题目链接:http://acdream.info/problem?pid=1216 -->>容易想到是一个二维的LIS模型..

ACdream 1216——Beautiful People——————【二维LIS,nlogn处理】

Beautiful People Special Judge Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statistic Next Problem Problem Description The most prestigious sports club in one city has exactly N members. Each of its members

ACdream 1216 (ASC训练1) Beautiful People(DP)

题目地址:http://acdream.info/problem?pid=1216 这题一开始用的是线段树,后来发现查询的时候还需要DP处理,挺麻烦..也就不了了之了..后来想到,这题其实就是一个二维的最长上升子序列.. 要先排序,先按左边的数为第一关键字进行升序排序,再按右边的数为第二关键字进行降序排序.这样的话,第一关键字相同的的肯定不在一个同一个上升子序列中.然后只对第二关键字进行复杂度为O(n*logn)的DP,找出最长上升序列,然后处理前驱,并输出即可. 代码如下: #include