I - Beautiful People ZOJ - 2319 (二分法)
The 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 2005 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.
This problem contains multiple test cases!
The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.
The output format consists of N output blocks. There is a blank line between output blocks.
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 - Si and Bi respectively (1 <= Si, Bi <= 109).
<p< dd="">
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.
<p< dd="">
Sample Input
1
4
1 1
1 2
2 1
2 2
<p< dd="">
Sample Output
2
1 4
题意:如果S1<=S2 && beaut1>=beaut2 或 S1>=S2 && beaut1<=beaut2那他们就是敌人,不可以一起出现在party,且要满足如果一号人的综合实力大于二号,且二号大于三号,那么一号和三号就不是敌人
思路:我们可以将条件转换一下,题上所给的条件比较复杂,但是转化为s1>s2 && beaut1>beaut2这样就感觉清晰了,这不就是最长上升子序列嘛
于是我们可以先对他的一个属性排序,当着一个属性相同时再对另一个属性反向排序(就是这两个属性的排序方式不同)
但是求最长上升子序列不能用平常的方法,要用优化的nlogn的方法(二分法)
但是二分法求出来的序列并不符合题意,但是它的长度是符合题意得,所以我们要在这个过程中记录其中间的变化,以来求出来符合题意的序列
要注意的是:二分法求出来的序列本来就不符合题意,如果有的例子过了,要就一定是碰巧,真正的序列要另开一个数据来存
举个例子:
输入:
1 2
1 3
3 12
2 9
2 7
3 10
2 1
对这几个数据的s进行从小到大排序,beaut进行从大到小
排序后:
1 3
1 2
2 9
2 7
2 1
3 12
3 10
按照二分法我们要一个dp数组来存二分求出来的序列(不符合题意得序列),和一个记录标号的数组pre
此时只需要求beaut的最长上升子序列
dp 3
pre 1
dp 2 2小于三所以要替换他的位置,以达到上升子序列的目的
pre 1 1
dp 2 9
pre 1 1 2
dp 2 7
pre 1 1 2 2
dp 1 7 找的是刚好大于或等于此值的位置,并和其交换
pre 1 1 2 2 1
dp 1 7 12
pre 1 1 2 2 1 3
dp 1 7 10
(头)pre 1 1 2 2 1 3 3(尾)
此时最长上升子序列的长度是3(用k来代替),所以我们要从pre数组的n循环找到1,从中找到符合题意的序列
从pre数组尾开始,如果里面存的值等于k,就输出此处序列下标所对应的原输入的序号(看一下代码理解一下),再让k--
为什么要这样输出:
因为二分法可以得到最长递增子序列的长度,所以输出的长度已经被确定,pre里面存的值是此时i的值在排序后可以放的位置
怎么保证输出的数的s不会重复:
其实我们让s和beaut的排序顺序相反正是为了这一点
假比我们可以输出两个s相同的值
那么就必须会出现2 3这样连续的递增序列在pre中,但是这是不可能出现的,按我们本题的排序方法beaut从大到小,那么后面的值要么替换前面的值,要么就在特别前面,不会连续出现(自己试一下吧!讲不出来<_>)
代码如下:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0xfffffff;
#define N 100000+10
#define inf 0x3f3f3f3f
struct shudui
{
int id;
int st,value;
}m[N];
bool cmp(shudui n1,shudui n2)
{
if(n1.st==n2.st)
return n1.value>n2.value; //用小的b值来覆盖大的b值
return n1.st<n2.st;
}
int pre[],dp[];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=; i<=n; ++i)
{
scanf("%d%d",&m[i].st,&m[i].value);
m[i].id=i;
}
memset(dp,inf,sizeof(dp)); //不能用INF来初始化数据,如果用的话,数组里面的值全部是-1
// for(int i=1;i<=n;++i)
// printf("%d ",dp[i]);
// printf("\n");
sort(m+,m++n,cmp);
//int g1,g2,g3; int k=;
// for(int i=1;i<=n;++i)
// {
// int j=lower_bound(dp+1,dp+1+n,m[i].value)-dp;
// dp[j]=m[i].value;
// pre[i]=j;
// k=max(k,j);
// }
// printf("%d\n",k);
// for(int i=n;i>=1;--i)
// {
// if(pre[i]==k)
// {
// printf("%d ",m[i].id);
// k--;
// }
// }
// printf("\n");
// if(t!=0) printf("\n");
for(int i=; i<=n; i++)
{
int j=lower_bound(dp+,dp++n,m[i].value)-dp;
dp[j]=m[i].value;
pre[i]=j;
k=max(k,j);
}
printf("%d\n",k);
for(int i=n; i>=; i--)
{
if (pre[i]==k)
{
printf("%d ",m[i].id);
k--;
}
}
printf("\n");
if(t!=)
{
printf("\n");
}
}
return ;
}
另外再讲一下二分法的使用
二分法主要分为两种
一、整数型(这样的二分好写)
high=1e9;
int maxn;
while(low<=1e9)
{
int mid=(low+high);
if(条件满足) {
maxn=mid;
low=mid+ or high=mid-; //具体要看题目
}
else if(>){
high=mid-;
}
else low=mid+;
}
另外还有一种是实数型
while(low-high<1e-)
{
double mid=(low+high)>>;
if(>) low=mid;
else high=mid;
}
//最后输出low或者是high,(这个还没有搞懂<_>)
I - Beautiful People ZOJ - 2319 (二分法)的更多相关文章
- ZOJ 2319 Beautiful People
LIS.先按S降序升序再按B降序排序(如果B不按降序排序的话就会覆盖掉正解),然后再对B用O(nlog(n))的LIS求解就可以了.用d数组标记每个元素在上升序列中的位置,然后根据d倒着找id就可以了 ...
- Beautiful People SGU - 199 ZOJ - 2319
最长上升子序列O(n log n):http://www.cnblogs.com/hehe54321/p/cf-340d.html 题目:https://cn.vjudge.net/problem/Z ...
- ZOJ 2319 Beatuiful People(单调递增序列的变形)
Beautiful People Time Limit: 5 Seconds Memory Limit: 32768 KB Special Judge The most prest ...
- ASC #1
开始套题训练,第一套ASC题目,记住不放过每一题,多独立思考. Problem A ZOJ 2313 Chinese Girls' Amusement 循环节 题意:给定n,为圆环长度,求k < ...
- HDU 4430 & ZOJ 3665 Yukari's Birthday(二分法+枚举)
主题链接: HDU:pid=4430" target="_blank">http://acm.hdu.edu.cn/showproblem.php?pid=4430 ...
- uva live 6190 Beautiful Spacing (二分法+dp试 基于优化的独特性质)
I - Beautiful Spacing Time Limit:8000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu ...
- zoj 3665 数论 二分法 两个参数
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4888 标题两个参数,途径:小参数的枚举,然后二分法大参数 想想两个点.以后就不 ...
- zoj Beautiful Number(打表)
题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2829 题目描述: Mike is very lucky, as ...
- zoj 2829 Beautiful Number
Beautiful Number Time Limit: 2 Seconds Memory Limit: 65536 KB Mike is very lucky, as he has two ...
随机推荐
- centos7之zabbix邮件报警(短信报警)
前言 前面我们介绍了zabbix的基本linux和window及SNMP流量的简单监控,我们知道作为运维人员,需要7x24小时待命,但是我们不可能时时刻刻都坐在电脑旁边查看监控上的各个主机状态,所以我 ...
- Java中的Null是什么?
对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰.连Java的发明者都承认这是他的一项巨大失误.Java为什么要保留null呢?null出现有一段时间了,并且我认 ...
- BZOJ3527[Zjoi2014]力——FFT
题目描述 给出n个数qi,给出Fj的定义如下: 令Ei=Fi/qi,求Ei. 输入 第一行一个整数n. 接下来n行每行输入一个数,第i行表示qi. n≤100000,0<qi<100000 ...
- python sorted函数多条件排序是怎么回事
首先,要知道sorted 内部实现使用了归并排序,而归并排序是稳定的排序,就是说当元素比不出大小时,其相对位置是不变的. 那么,利用稳定排序的特性,key函数有几个返回值就排序几次,先排序次要条件,后 ...
- Multi-View 3D Reconstruction with Geometry and Shading——Part-1
From PhDTheses Multi-View 3D Reconstruction with Geometry and Shading 计算机视觉的主要任务就是利用图像信息能智能理解周围的世界. ...
- 关于 iOS 性能优化方面的面试题,
这是我前面几天碰到的面试题: 如何对定位和分析项目中影响性能的地方?以及如何进行性能优化? 我的答案: 定位方法: instruments 在iOS上进行性能分析的时候,首先考虑借助instrum ...
- python全栈开发中级班全程笔记(第二模块、第四章(三、re 正则表达式))
python全栈开发笔记第二模块 第四章 :常用模块(第三部分) 一.正则表达式的作用与方法 正则表达式是什么呢?一个问题带来正则表达式的重要性和作用 有一个需求 : 从文件中读取所有联 ...
- Httpclient发送json请求
一.Httpclient发送json请求 public String RequestJsonPost(String url){ String strresponse = null; try ...
- JS基础-第5天
复习函数 函数 作用:封装一段代码,封装的功能可以被反复调用执行. 定义函数 // 第一种 - 函数声明 function 函数名(){ } // 第二种 - 函数表达式 var 函数名 = func ...
- ConcurrentHashMap扩容
然后,说说精华的部分. Cmap 支持并发扩容,实现方式是,将表拆分,让每个线程处理自己的区间.如下图: 假设总长度是 64 ,每个线程可以分到 16 个桶,各自处理,不会互相影响. 而每个线 ...