zoukankan      html  css  js  c++  java
  • 【luogu P2947 [USACO09MAR]向右看齐Look Up】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2947

    因为在单调队列上被dalao们锤爆

    怒刷单调队列题

    何为单调队列?

    设我们的队列为从左至右单调递增

    对于样例数据 3 2 6 1 1 2

    我们先把3入队 此时队列:3

    再将2从后面入队 此时队列:2 3

    再将6从后面入队 但是,为了满足队列从左至右的单调性,我们将2,3出队 此时队列:6

    再将1从后面入队 此时队列:1 6

    再将1从后面入队 此时队列:1 1 6

    再将2从后面入队 但是,为了满足队列从左至右的单调性,我们将1,1出队 此时队列:2 6

    由此可以类推其他单调性。

    于是,我们观察到单调队列和这道题的关系:

    “谁把我从队列里赶了出去我就仰望谁。”

    所以,2,3被6赶出去,2,3仰望的位置为6的位置即3。

    所以,1,1被2赶出去,1,1仰望的位置为2的位置即6。

    那么,如果我一直在队里。我就谁也不仰望。

    下面介绍实现方式:

    我先说:

    "我永远都喜欢(Stella)!"

    没良心的Master

    单调队列需要一个支持从两边操作的队列——双端队列

    (STL)中有现成的deque:

    (code:)

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn = 100000 + 10;
    struct node{
    	int pos, val;
    }a[maxn];//因为我们需要记录位置,所以开一个结构体。val为高度,pos为在序列的位置。
    int n, ans[maxn];
    deque<node> q;//双端队列。
    int main()
    {
    	scanf("%d",&n);
    	for(int i = 1; i <= n; i++)
    	{
    		scanf("%d",&a[i].val); a[i].pos = i;//输入高度,给位置赋值。
    		while(!q.empty() && a[i].val > q.back().val) ans[q.back().pos] = a[i].pos, q.pop_back();//当队列不为空时,如果当前输入的值大于我队列中后面的元素值,那么我就要仰望当前的输入值的位置。同时把我出队。
    		q.push_back(a[i]);//从后面将元素入队。
    	}
    	for(int i = 1; i <= n; i++) 
    	printf("%d
    ",ans[i]);
    	return 0;
    }
    

    至于为什么需要一个支持两头操作的队列。

    在大部分单调队列题目中,需要维护的区间有时并不是整一个区间,而是多个区间。所以当如果我们单调队列中最前面的数已经不在当前区间里,我们需要将他从前面出队。

    最前面的数一定比当前维护好的队列里所有数入队都早。如果他入队不是最早还比之前入队的数大,前面入队的数直接被他挤出队了。

    欢迎交流/指错

    一起共同进步。

    QQ:935145183/3203600070

  • 相关阅读:
    【BZOJ 4151 The Cave】
    【POJ 3080 Blue Jeans】
    【ZBH选讲·树变环】
    【ZBH选讲·拍照】
    【ZBH选讲·模数和】
    【CF Edu 28 C. Four Segments】
    【CF Edu 28 A. Curriculum Vitae】
    【CF Edu 28 B. Math Show】
    【CF Round 439 E. The Untended Antiquity】
    【CF Round 439 C. The Intriguing Obsession】
  • 原文地址:https://www.cnblogs.com/MisakaAzusa/p/9427006.html
Copyright © 2011-2022 走看看