POJ 3670 Eating Together 二分解法O(nlgn)和O(n)算法
本题就是一题LIS(最长递增子序列)的问题。本题要求求最长递增子序列和最长递减子序列。
dp的解法是O(n*n),这个应该大家都知道。只是本题应该超时了。
由于有O(nlgn)的解法。
可是因为本题的数据特殊性。故此本题能够利用这个特殊性加速到O(n)的解法。当中的底层思想是counting sort分段的思想。就是假设你不会counting sort的话,就非常难想出这样的优化的算法了。
O(nlgn)的利用单调队列性质的解法,利用二分加速是有代表性的,无数据特殊的时候也能够使用。故此这里先给出这个算法代码。
看了代码就知道非常easy的了,只是这里为了更加高效利用代码,就使用了函数指针,代码十分简洁了,刚開始学习的人耐心点看,代码应该非常好的:
#include <stdio.h> const int MAX_N = 30000;
int arr1[MAX_N], arr2[MAX_N];
inline int max(int a, int b) { return a > b? a : b; } inline bool larEqu(int a, int b) { return a <= b; }
inline bool smaEqu(int a, int b) { return a >= b; } int biSearch(int low, int up, int val, bool (*func)(int , int))
{
while (low <= up)
{
int mid = low + ((up-low)>>1);
if (func(val, arr2[mid])) low = mid+1;
else up = mid-1;
}
return low;
} int getLIS(int n, bool (*func)(int, int))
{
int j = 0;
arr2[0] = arr1[0];
for (int i = 1; i < n; i++)
{
if (func(arr1[i], arr2[j])) arr2[++j] = arr1[i];
else arr2[biSearch(0, j, arr1[i], func)] = arr1[i];
}
return j+1;
} int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
for (int i = 0; i < n; i++)
{
scanf("%d", &arr1[i]);
}
printf("%d\n", n-max(getLIS(n, larEqu), getLIS(n, smaEqu)));
}
return 0;
}
然后是O(n)的时间效率的算法。
就是由于仅仅有1,2,3,这三个数据,故此能够分开窗体。分别记录1。 2, 3 的数据段,在利用上面单调队列的思想的时候,就能够不使用二分法了,而是直接插入就能够了,故此省去了lgn的时间。时间效率就优化到O(n)了。
这个算法卡了我的地方就是下标的问题,老是无法准确记录窗体下标的,故此这里使用个特殊的记录下标的方法。看代码就好像是个O(n*n)的算法。由于循环中有循环。可是大家细致看,事实上这是个O(n)算法。为什么呢?由于循环中的循环总共仅仅是搜索了一遍n个数。无需反复搜索。
#include <stdio.h> const int MAX_N = 30000;
int arr1[MAX_N], arr2[MAX_N];
inline int max(int a, int b) { return a > b? a : b; } int getLIS(int n)
{
int j = 0, one = 0, two = 0;
arr2[0] = arr1[0];
for (int i = 1; i < n; i++)
{
if (arr1[i] >= arr2[j])
{
arr2[++j] = arr1[i];
}
else
{
if (arr1[i] == 1)
{
while (arr2[one] < 2 && one < j) one++;
arr2[one] = arr1[i];
}
else
{
while (arr2[two] < 3 && two < j) two++;
arr2[two] = arr1[i];
}
}
}
return j+1;
} int getLDS(int n)
{
int j = 0, two = 0, thr = 0;
arr2[0] = arr1[0];
for (int i = 1; i < n; i++)
{
if (arr1[i] <= arr2[j]) arr2[++j] = arr1[i];
else
{
if (arr1[i] == 3)
{
while (arr2[thr] > 2 && thr < j) thr++;
arr2[thr] = arr1[i];
}
else
{
while (arr2[two] > 1 && two < j) two++;
arr2[two] = arr1[i];
}
}
}
return j+1;
} int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
for (int i = 0; i < n; i++)
{
scanf("%d", &arr1[i]);
}
printf("%d\n", n-max(getLIS(n), getLDS(n)));
}
return 0;
}
POJ 3670 Eating Together 二分解法O(nlgn)和O(n)算法的更多相关文章
- POJ 3670 Eating Together (DP,LIS)
题意:给定 n 个数,让你修改最少的数,使得它变成一个不下降或者不上升序列. 析:这个就是一个LIS,但是当时并没有看出来...只要求出最长LIS的长度,用总数减去就是答案. 代码如下: #inclu ...
- POJ 3670 Eating Together(LIS)
Description The cows are so very silly about their dinner partners. They have organized themselves i ...
- poj 2456 Aggressive cows 二分 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=2456 解法 使用二分逐个尝试间隔距离 能否满足要求 检验是否满足要求的函数 使用的思想是贪心 第一个点放一头牛 后面大于等于尝试的距离才放 ...
- POJ 3273 Monthly Expense二分查找[最小化最大值问题]
POJ 3273 Monthly Expense二分查找(最大值最小化问题) 题目:Monthly Expense Description Farmer John is an astounding a ...
- [POJ 2821]TN's Kindom III(任意长度循环卷积的Bluestein算法)
[POJ 2821]TN's Kindom III(任意长度循环卷积的Bluestein算法) 题面 给出两个长度为\(n\)的序列\(B,C\),已知\(A\)和\(B\)的循环卷积为\(C\),求 ...
- poj 3258 River Hopscotch(二分+贪心)
题目:http://poj.org/problem?id=3258 题意: 一条河长度为 L,河的起点(Start)和终点(End)分别有2块石头,S到E的距离就是L. 河中有n块石头,每块石头到S都 ...
- POJ 1064 Cable master (二分答案)
题目链接:http://poj.org/problem?id=1064 有n条绳子,长度分别是Li.问你要是从中切出m条长度相同的绳子,问你这m条绳子每条最长是多少. 二分答案,尤其注意精度问题.我觉 ...
- POJ 3670 , 3671 LIS
题意:两题意思差不多,都是给你一个序列,然后求最少需要改变多少个数字,使得成为一个最长不升,或者最长不降子序列. 当然3671是只能升序,所以更简单一点. 然后就没有什么了,用二分的方法求LIS即可. ...
- POJ 3273 Monthly Expense 二分枚举
题目:http://poj.org/problem?id=3273 二分枚举,据说是经典题,看了题解才做的,暂时还没有完全理解.. #include <stdio.h> #include ...
随机推荐
- Splunk的安装与使用
一.简单介绍 Splunk 是机器数据的引擎.使用 Splunk 可收集.索引和利用全部应用程序.server和设备(物理.虚拟和云中)生成的高速移动型计算机数据 .从一个位置搜索并分 ...
- Ubuntu14.04下Neo4j图数据库官网安装部署步骤(图文详解)(博主推荐)
不多说,直接上干货! 说在前面的话 首先,查看下你的操作系统的版本. root@zhouls-virtual-machine:~# cat /etc/issue Ubuntu 14.04.4 LTS ...
- linux安装scikit-learn
原文:http://www.cnblogs.com/cyttina/archive/2013/06/08/3127345.html ubuntu的看官方的文档就好了. http://scikit-le ...
- C#.NET常见问题(FAQ)-如何引用定义好的dll文件
1 添加引用,找到dll文件 2 引用类的名称空间,生成类的实例,调用类的方法,测试OK. 更多教学视频和资料下载,欢迎关注以下信息: 我的优酷空间: http://i.youku.com ...
- 如何使用千千静听为MP3添加专辑封面和文字信息
使用千千静听播放器打开某MP3文件,右击该文件,选择属性. 2 点击专辑封面即可添加或更换专辑封面 点击保存到文件再点击重新读取文件即可发现有效了 3 为MP3批量添加添加封面 选中播放列表的所有文件 ...
- Android Bundle存储数据类型
曾经被问到这样一个问题:Bundle能存哪些数据类型,不能存哪些数据类型? 当时那个汗啊,因为,平常使用Bundle,要么使用基本数据类型,要么序列化自定义的Class,那到底能存哪些类型,不能存哪些 ...
- 微信小程序 - 自定义tabbar
更新: 2019-1-18:自定义tabbar组件已发布 各种奇葩的需求,造就了我们 wxml <view class="nav-tabs"> <view cla ...
- Linux安装 微信开发者工具(deepin linux ubt)
一.环境:: deepin linux15.4.1 二.安装过程: 2.1 安装wine sudo apt-get install wine 2.2 安装nwjs-sdk 2.2.1 下载linux版 ...
- Java从零开始学三(public class和class)
使用public class和class声明的区别 public class文件名称必须与类名称一致 class文件名称可以与类名称不一致
- ssh2的application.xml配置文件配置详解
ssh2的application.xml配置文件配置详解 1.导入其他的配置文件.在ssh项目中可以导入其他的配置文件,导入的格式为: <import resource="clas ...