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 ...
随机推荐
- 浅谈jQuery easyui datagrid操作单元格样式
今天项目上遇到问题,就是表格风格统一的问题,由于用了2个不同的框架,所以如果要大修比较麻烦,考虑到修改表格样式工作量会少很多,所以考虑修改jQuery easyui datagrid数据网格的样式. ...
- Cognos审核模块的导入与设置
Cognos审核模块:就是指针对Cognos在运行过程中的对象被执行和访问的日志记录做了一个对象包,在该包里面我们可以从报表里面看到一些日志记录.以方便我们对Cognos的执行记录进行查看,下面我来说 ...
- Android-Bundle认知、和Intent的差别
不时的回过头来看看自己的Andriod学习.实践之路,总发现有些曾经不明确的,如今清楚缘由.也会发现一些之前没怎么关注的.如今看到了 ,很想去深刻了解的. 比方:Bundle. 在一个Activity ...
- vs2013 密钥_
vs2013 密钥 最佳答案: BWG7X-J98B3-W34RT-33B3R-JVYW9
- UE查找和替换技巧实例
1 删除多余的空行 如果是在WORD中,则查找^p^p替换为^p. 如果是在EXCEL里,则为全部选中,然后点击编辑,定位,定位条件,空值. 将全部选中空白的行,如图所示 再次点击编辑,删除,删除整行 ...
- Python编程-Office操作-操作Excel(中)
例子文件如下: 一些复杂的读取操作getCells.py import openpyxl wb = openpyxl.load_workbook('example.xlsx') sheet = wb. ...
- UVA 10026 Shoemaker's Problem 鞋匠的难题 贪心+排序
题意:鞋匠一口气接到了不少生意,但是做鞋需要时间,鞋匠只能一双一双地做,根据协议每笔生意如果拖延了要罚钱. 给出每笔生意需要的天数和每天的罚钱数,求出最小罚钱的排列顺序. 只要按罚款/天数去从大到小排 ...
- uni-app 如何引入全局方法或变量?
利用Vue.prototype挂载到Vue实例上即可
- more命令(转)
原文:http://www.cnblogs.com/peida/archive/2012/11/02/2750588.html more命令,功能类似 cat ,cat命令是整个文件的内容从上到下显示 ...
- POSIX 线程详解
一种支持内存共享的简捷工具 POSIX(可移植操作系统接口)线程是提高代码响应和性能的有力手段.在本系列中,Daniel Robbins 向您精确地展示在编程中如何使用线程.其中还涉及大量幕后细节,读 ...