此题用java解和C++解,差距足够足够大,如下图
原题
http://poj.org/problem?id=2823
解题思路
这题还可以用单调队列进行求解。开两个队列,一个维护最大值,一个维护最小值。下面叙述最大队列,最小队列的方法类似。
最大队列保证队列中各个元素大小单调递减(注意,不是单调不上升),同时每个元素的下标单调递增。这样便保证队首元素最大,而且更新的时候队首永远是当前最大。因此,这个队列需要在两头都可以进行删除,在队尾插入。
维护方法:
在每次插入的时候,先判断队尾元素,如果不比待插入元素大就删除,不断删除队尾直到队尾元素大于待插入元素或者队空。删除的时候,判断队首,如果队首元素下标小于当前段左边界就删除,不断删除队首直到队首元素下标大于等于当前段左边界(注意:这时队列肯定不为空),队首元素就是当前段的最优解。
#include<algorithm>
using namespace std;
int a[1000011];//数组数据
int Q[1000011];//队列
int I[1000011];//I[i]表示队列中的Q[i]在数组中的下标
int OutMin[1000011];//最小值
int OutMax[1000011];//最大值
int n,k;
void GetMin()
{
int i;
int head=1;
int tail=0;
for(i=1;i<k;++i)
{
while(head <=tail && Q[tail]>a[i])
tail--;
tail++;
Q[tail]=a[i];
I[tail]=i;
}
for(i=k;i<=n;++i)
{
while(head <=tail && Q[tail]>a[i])
tail--;
tail++;
Q[tail]=a[i];
I[tail]=i;
while(I[head]<=i-k)
head++;
OutMin[i-k] = Q[head];
}
}
void GetMax()
{
int i;
int head=1;
int tail=0;
for(i=1;i<k;++i)
{
while(head <=tail && Q[tail]<a[i])
tail--;
tail++;
Q[tail]=a[i];
I[tail]=i;
}
for(i=k;i<=n;++i)
{
while(head <=tail && Q[tail]<a[i])
tail--;
tail++;
Q[tail]=a[i];
I[tail]=i;
while(I[head]<=i-k)
head++;
OutMax[i-k]=Q[head];
}
}
int main()
{
int i;
scanf("%d%d",&n,&k);
if(k>n)
k=n;
for(i=1;i<=n;++i)
{
scanf("%d",&a[i]);
}
GetMin();
GetMax();
for(i=0;i<=(n-k);++i)
{
printf("%d%c", OutMin[i], (i < n - k) ? ' ' : '\n');
}
for(i=0;i<=(n-k);++i)
{
printf("%d%c", OutMax[i], (i < n - k) ? ' ' : '\n');
}
return 0;
}
import java.util.Scanner;
public class Main{
Scanner scan=new Scanner(System.in);
int n,k;
int[] queue=new int[1000005];
int[] Index=new int[1000005];
int[] arr=new int[1000005];
int[] MIN=new int[1000005];
int[] MAX=new int[1000005];
public static void main(String[] args){
new Main().run();
}
void run(){
n=scan.nextInt();
k=scan.nextInt();
if(k>n)
k=n;
for(int i=1;i<=n;i++)
{
arr[i]=scan.nextInt();
}
GetMin();
GetMax();
for(int i=0;i<=(n-k);i++)
{
System.out.print(MIN[i]+" ");
}
System.out.println();
for(int i=0;i<=(n-k);i++)
{
System.out.print(MAX[i]+" ");
}
}
void GetMin(){
int head=1;
int tail=0;
for(int i=1;i<k;i++)
{
while(head<=tail&&queue[tail]>arr[i])
tail--;
tail++;
queue[tail]=arr[i];
Index[tail]=i;
}
for(int i=k;i<=n;i++)
{
while(head<=tail&&queue[tail]>arr[i])
tail--;
tail++;
queue[tail]=arr[i];
Index[tail]=i;
while(Index[head]<=i-k)
head++;
MIN[i-k]=queue[head];
}
}
void GetMax(){
int head=1;
int tail=0;
for(int i=1;i<k;i++)
{
while(head<=tail&&queue[tail]<arr[i])
tail--;
tail++;
queue[tail]=arr[i];
Index[tail]=i;
}
for(int i=k;i<=n;i++)
{
while(head<=tail&&queue[tail]<arr[i])
tail--;
tail++;
queue[tail]=arr[i];
Index[tail]=i;
while(Index[head]<=i-k)
head++;
MAX[i-k]=queue[head];
}
}
}
- 大小: 12.8 KB
- 大小: 25.4 KB
分享到:
相关推荐
我的博客链接:http://blog.csdn.net/CABI_ZGX
单调队列优化动态规划广泛应用于解决滑动窗口问题,例如POJ 2823 Sliding Window、P1886 滑动窗口等。这些问题都可以使用单调队列优化动态规划来解决。 实现方法 单调队列优化动态规划的实现方法可以分为以下几步...
- **POJ2823 Sliding Window**:该问题给出一个序列和一个窗口大小k,需要计算在每个位置时,窗口内的最大值或最小值。可以使用单调队列优化将时间复杂度从O(nk)降低至O(n)。 - **最大连续和**:这是一个经典的动态...
### DP的单调队列优化详解 #### 一、单调队列简介 单调队列是一种特殊的数据结构,主要用于处理滑动窗口中的最值问题。在算法竞赛中,尤其是在DP(动态规划)问题中,通过利用单调队列可以有效地优化时间复杂度。 ...
### 单调栈与单调队列详解 #### 一、单调栈 **定义:** 单调栈是一种特殊的数据结构,其内部存储的元素按照单调递增或单调递减的方式排序。当有新的元素需要加入栈时,若这个元素破坏了当前栈内元素的单调性,则...
如二分法用于逼近单调函数的根,提高算法效率,见poj3273和poj3258。 ### 七、计算几何学 #### 几何公式与运算 叉积和点积用于判断线段交叉、计算点到线段距离等,如poj2031。 #### 多边形算法 包括求多边形面积...
- **计算方法**:如二分法求解单调函数,如poj3273。 7. **计算几何**: - **几何公式**:用于解决几何问题。 - **叉积与点积**:辅助判断线段相交、点到线段距离等,如poj2031。 - **多边形算法**:如求面积、...
- **应用场景**:适用于实现优先队列、堆排序等问题。 **7. Trie 树** - **定义**:一种用于存储字符串集合的树形结构。 - **示例题目**: - poj2513 - **应用场景**:适用于字符串检索、自动补全等功能。 #### ...
在处理蚯蚓生长的问题时,单调队列可以帮助我们在每次操作时快速找到需要处理的蚯蚓,同时维持队列的有序性,使得更新操作更为高效。 总结来说,队列是一种基础且重要的数据结构,它在很多实际问题中都有应用。通过...
3. **计算方法**:掌握二分法求解单调函数问题,如POJ3273、3258、1905和3122。 ### 计算几何学 1. **几何公式**:理解和应用几何原理。 2. **叉积和点积**:用于判断线段相交、计算距离等,如POJ2031和1039。 3. *...
这是来自poj的一道关于单调队列的题目。分为max_qu和min_qu两部分来做。
【专辑】单调队列+斜率优化的DP 01背包问题 acm动态规划总结 PKU——DP专辑 背包之01 POJ 动态规划总结 背包之01背包、完全背包、多重背包详解 Dynamic+Programming 典型的动态规划,用递归下的记忆化搜索来实现 ...
3. 计算方法:二分法解决单调函数问题,如poj3273、poj3258等。 七、计算几何学 1. 几何公式:如点、线、面的关系。 2. 叉积和点积:用于判断线段相交和距离计算,如poj2031、poj1039。 3. 多边形:求面积和相关...
- **计算方法**:理解二分法求解单调函数问题,如Poj3273、Poj3258等。 7. **计算几何** - **几何公式**:学习基础几何知识。 - **叉积和点积**:用于判断线段相交、计算距离等,如Poj2031、Poj1039。 - **...
然后,构建两个单调链,即每条链上的点在y轴上非降序排列,最后合并这两条链以形成凸包。 3. **QuickHull算法**:这是一种类似于快速排序的分治算法,通过不断分割空间直到每个子空间中只包含一个点,从而达到求解...
- **堆**:用于优先队列和最值问题。 - **Trie 树**:高效存储和查找字符串,分为静态建树和动态建树。 4. **简单搜索**: - **深度优先搜索(DFS)**:poj2488、poj3083 等。 - **广度优先搜索(BFS)**:poj...
**应用实例**:**POJ2823 SlidingWindow** - **问题描述**:给定一个长度为`N`的数组,一个长度为`K`的滑动窗口从最左端移动到最右端。对于窗口的每种位置,求出窗口覆盖的`K`个数中的最小值和最大值。 - **数据...
3. **计算方法**:二分法求解单调函数,如POJ3273。 **计算几何学** 1. **几何公式**:涉及几何计算。 2. **叉积和点积**:用于线段相交检测和距离计算,如POJ2031。 3. **多边形算法**:求面积、点在多边形内的...