`
believexkx
  • 浏览: 22606 次
  • 性别: Icon_minigender_2
  • 来自: 济南
社区版块
存档分类
最新评论

POJ2823 单调队列

阅读更多
此题用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
0
4
分享到:
评论

相关推荐

    [POJ2823]Sliding Window(单调队列)by_zgx优化最新版

    我的博客链接:http://blog.csdn.net/CABI_ZGX

    第5章 单调队列优化动态规划(2021.08.23).pdf

    单调队列优化动态规划广泛应用于解决滑动窗口问题,例如POJ 2823 Sliding Window、P1886 滑动窗口等。这些问题都可以使用单调队列优化动态规划来解决。 实现方法 单调队列优化动态规划的实现方法可以分为以下几步...

    第5章 单调队列优化动态规划(2021.08.19).pdf

    - **POJ2823 Sliding Window**:该问题给出一个序列和一个窗口大小k,需要计算在每个位置时,窗口内的最大值或最小值。可以使用单调队列优化将时间复杂度从O(nk)降低至O(n)。 - **最大连续和**:这是一个经典的动态...

    DP的单调队列优化-Yuiffy.pdf

    ### DP的单调队列优化详解 #### 一、单调队列简介 单调队列是一种特殊的数据结构,主要用于处理滑动窗口中的最值问题。在算法竞赛中,尤其是在DP(动态规划)问题中,通过利用单调队列可以有效地优化时间复杂度。 ...

    单调栈和单调队列.pdf

    ### 单调栈与单调队列详解 #### 一、单调栈 **定义:** 单调栈是一种特殊的数据结构,其内部存储的元素按照单调递增或单调递减的方式排序。当有新的元素需要加入栈时,若这个元素破坏了当前栈内元素的单调性,则...

    poj各种分类

    如二分法用于逼近单调函数的根,提高算法效率,见poj3273和poj3258。 ### 七、计算几何学 #### 几何公式与运算 叉积和点积用于判断线段交叉、计算点到线段距离等,如poj2031。 #### 多边形算法 包括求多边形面积...

    POJ题目简单分类(ACM)

    - **计算方法**:如二分法求解单调函数,如poj3273。 7. **计算几何**: - **几何公式**:用于解决几何问题。 - **叉积与点积**:辅助判断线段相交、点到线段距离等,如poj2031。 - **多边形算法**:如求面积、...

    POJ 分类题目

    - **应用场景**:适用于实现优先队列、堆排序等问题。 **7. Trie 树** - **定义**:一种用于存储字符串集合的树形结构。 - **示例题目**: - poj2513 - **应用场景**:适用于字符串检索、自动补全等功能。 #### ...

    0x12 队列.pptx

    在处理蚯蚓生长的问题时,单调队列可以帮助我们在每次操作时快速找到需要处理的蚯蚓,同时维持队列的有序性,使得更新操作更为高效。 总结来说,队列是一种基础且重要的数据结构,它在很多实际问题中都有应用。通过...

    强大的POJ分类——各类编程简单题及其算法分类

    3. **计算方法**:掌握二分法求解单调函数问题,如POJ3273、3258、1905和3122。 ### 计算几何学 1. **几何公式**:理解和应用几何原理。 2. **叉积和点积**:用于判断线段相交、计算距离等,如POJ2031和1039。 3. *...

    Sliding Window

    这是来自poj的一道关于单调队列的题目。分为max_qu和min_qu两部分来做。

    经典动态规划合集_牛人 树形,压缩 老题

    【专辑】单调队列+斜率优化的DP 01背包问题 acm动态规划总结 PKU——DP专辑 背包之01 POJ 动态规划总结 背包之01背包、完全背包、多重背包详解 Dynamic+Programming 典型的动态规划,用递归下的记忆化搜索来实现 ...

    ACM算法总结大全——超有用!

    3. 计算方法:二分法解决单调函数问题,如poj3273、poj3258等。 七、计算几何学 1. 几何公式:如点、线、面的关系。 2. 叉积和点积:用于判断线段相交和距离计算,如poj2031、poj1039。 3. 多边形:求面积和相关...

    很快速的提高算法能力.docx

    - **计算方法**:理解二分法求解单调函数问题,如Poj3273、Poj3258等。 7. **计算几何** - **几何公式**:学习基础几何知识。 - **叉积和点积**:用于判断线段相交、计算距离等,如Poj2031、Poj1039。 - **...

    学习凸包(三):凸包练习 POJ 1113

    然后,构建两个单调链,即每条链上的点在y轴上非降序排列,最后合并这两条链以形成凸包。 3. **QuickHull算法**:这是一种类似于快速排序的分治算法,通过不断分割空间直到每个子空间中只包含一个点,从而达到求解...

    ACM 经验 笔记 很有用的经验指导

    - **堆**:用于优先队列和最值问题。 - **Trie 树**:高效存储和查找字符串,分为静态建树和动态建树。 4. **简单搜索**: - **深度优先搜索(DFS)**:poj2488、poj3083 等。 - **广度优先搜索(BFS)**:poj...

    NOIP 数据结构课件

    **应用实例**:**POJ2823 SlidingWindow** - **问题描述**:给定一个长度为`N`的数组,一个长度为`K`的滑动窗口从最左端移动到最右端。对于窗口的每种位置,求出窗口覆盖的`K`个数中的最小值和最大值。 - **数据...

    ACM算法总结大全——超有用!.pdf

    3. **计算方法**:二分法求解单调函数,如POJ3273。 **计算几何学** 1. **几何公式**:涉及几何计算。 2. **叉积和点积**:用于线段相交检测和距离计算,如POJ2031。 3. **多边形算法**:求面积、点在多边形内的...

Global site tag (gtag.js) - Google Analytics