本题就是一题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)算法的更多相关文章

  1. POJ 3670 Eating Together (DP,LIS)

    题意:给定 n 个数,让你修改最少的数,使得它变成一个不下降或者不上升序列. 析:这个就是一个LIS,但是当时并没有看出来...只要求出最长LIS的长度,用总数减去就是答案. 代码如下: #inclu ...

  2. POJ 3670 Eating Together(LIS)

    Description The cows are so very silly about their dinner partners. They have organized themselves i ...

  3. poj 2456 Aggressive cows 二分 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=2456 解法 使用二分逐个尝试间隔距离 能否满足要求 检验是否满足要求的函数 使用的思想是贪心 第一个点放一头牛 后面大于等于尝试的距离才放 ...

  4. POJ 3273 Monthly Expense二分查找[最小化最大值问题]

    POJ 3273 Monthly Expense二分查找(最大值最小化问题) 题目:Monthly Expense Description Farmer John is an astounding a ...

  5. [POJ 2821]TN's Kindom III(任意长度循环卷积的Bluestein算法)

    [POJ 2821]TN's Kindom III(任意长度循环卷积的Bluestein算法) 题面 给出两个长度为\(n\)的序列\(B,C\),已知\(A\)和\(B\)的循环卷积为\(C\),求 ...

  6. poj 3258 River Hopscotch(二分+贪心)

    题目:http://poj.org/problem?id=3258 题意: 一条河长度为 L,河的起点(Start)和终点(End)分别有2块石头,S到E的距离就是L. 河中有n块石头,每块石头到S都 ...

  7. POJ 1064 Cable master (二分答案)

    题目链接:http://poj.org/problem?id=1064 有n条绳子,长度分别是Li.问你要是从中切出m条长度相同的绳子,问你这m条绳子每条最长是多少. 二分答案,尤其注意精度问题.我觉 ...

  8. POJ 3670 , 3671 LIS

    题意:两题意思差不多,都是给你一个序列,然后求最少需要改变多少个数字,使得成为一个最长不升,或者最长不降子序列. 当然3671是只能升序,所以更简单一点. 然后就没有什么了,用二分的方法求LIS即可. ...

  9. POJ 3273 Monthly Expense 二分枚举

    题目:http://poj.org/problem?id=3273 二分枚举,据说是经典题,看了题解才做的,暂时还没有完全理解.. #include <stdio.h> #include ...

随机推荐

  1. 移动立方体算法(Marching cubes algorithm)

    百度百科: 医学图像三维重建的方法主要有两大类:一类是三维面绘制,另一类是三维体绘制.体绘制能够更真实地反映物体结构,但由于其运算量大,即使利用高性能的计算机也无法满足实际应用中交互操作的需要.因此, ...

  2. 微信小程序开发:设置消息推送

    开发设置中,启用并设置消息推送配置后,用户发给小程序的消息以及开发者需要的事件推送,都将被微信转发至该服务器地址中. 不过照着说明去操作,即使按照最简单的明文方式去设置,还是提示Token验证失败.仔 ...

  3. Sql server management studio: cannot find one or more components

      Install VS2010 SHELL 独立组件 https://www.microsoft.com/en-US/download/details.aspx?id=1366 运行安装程序,rep ...

  4. [Functional Programming 101] runWIth, evalWith, execWith

    Recentlly, I am learning crocks.js ADT libaray. In the beginning, it is hard to understand when to u ...

  5. python input 与raw_input函数的区别

    转自:http://blog.csdn.net/sruru/article/details/7790436 以前没有深入考虑过raw_input与input函数的区别,所以一直比较困惑,今天测试之后, ...

  6. ZH奶酪:IBG项目工作内容

    IBG项目技术概览 (HTML/CSS/JavaScript/AngularJS/PHP/MySQL): (1)后台:PHP Yii2.0 Framework (2)前端:Ionic Framewor ...

  7. UML 之 数据流图(DFD)

          数据流图(Data Flow Diagram):简称DFD,它从数据传递和加工角度,以图形方式来表达系统的逻辑功能.数据在系统内部的逻辑流向和逻辑变换过程,是结构化系统分析方法的主要表达工 ...

  8. Linux高性能server编程——多线程编程(下)

    多线程编程 条件变量 假设说相互排斥锁是用于同步线程对共享数据的訪问的话.那么条件变量则是用于线程之间同步共享数据的值. 条件变量提供了一种线程间的通信机制:当某个共享数据达到某个值得时候,唤醒等待这 ...

  9. TP5报错variable type error: array

      variable type error: array 当你在tp5框架中写方法时返回一个数组时,tp5会报错:variable type error: array 这是因为tp5不支持返回数组. ...

  10. java经典小程序

    1,编写程序,判断给定的某个年份是否是闰年. 闰年的判断规则如下: (1)若某个年份能被4整除但不能被100整除,则是闰年. (2)若某个年份能被400整除,则也是闰年. import java.ut ...