zoukankan      html  css  js  c++  java
  • [USACO09MAR]向右看齐Look Up(单调栈、在线处理)

    https://www.luogu.org/problem/P2947

    题目描述

    Farmer John's N (1 <= N <= 100,000) cows, conveniently numbered 1..N, are once again standing in a row. Cow i has height Hi (1 <= Hi <= 1,000,000).
    Each cow is looking to her left toward those with higher index numbers. We say that cow i 'looks up' to cow j if i < j and Hi < Hj. For each cow i, FJ would like to know the index of the first cow in line looked up to by cow i.
    Note: about 50% of the test data will have N <= 1,000.

    输入描述:

    * Line 1: A single integer: N
    * Lines 2..N+1: Line i+1 contains the single integer: Hi

    输出描述:

    * Lines 1..N: Line i contains a single integer representing the smallest index of a cow up to which cow i looks. If no such cow exists, print 0.

    示例1

    输入

    6 
    3 
    2 
    6 
    1 
    1 
    2 

    输出

    3
    3
    0
    6
    6
    0

    说明

    FJ has six cows of heights 3, 2, 6, 1, 1, and 2.
    Cows 1 and 2 both look up to cow 3; cows 4 and 5 both look up to cow 6; and cows 3 and 6 do not look up to any cow.

    找每个数右边第一个大于等于它的位置,并输出该位置,如果没有就输出0

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <iostream>
     4 #include <string>
     5 #include <math.h>
     6 #include <algorithm>
     7 #include <vector>
     8 #include <queue>
     9 #include <set>
    10 #include <map>
    11 #include <math.h>
    12 const int INF=0x3f3f3f3f;
    13 typedef long long LL;
    14 const int mod=1e9+7;
    15 const int maxn=1e5+10;
    16 using namespace std;
    17 
    18 int A[maxn]; 
    19 int ans[maxn];
    20 
    21 int main()
    22 {
    23     int n;
    24     scanf("%d",&n);
    25     for (int i=1;i<=n;i++)
    26         scanf("%d",&A[i]);
    27     vector<int> vt; 
    28     vt.push_back(1);
    29     int MIN=A[1];
    30     for (int i = 2; i <= n; i++)
    31     {
    32         if(A[i]>=MIN) 
    33         {
    34             while (!vt.empty()) 
    35             {
    36                 if (A[*(vt.end()-1)]<A[i])
    37                 {
    38                     ans[*(vt.end()-1)]=i;
    39                     vt.erase(vt.end()-1);
    40                 }
    41                 else
    42                     break;
    43             }
    44             vt.push_back(i);
    45         }
    46         else
    47         {
    48             vt.push_back(i);
    49             MIN=ans[i];
    50         }
    51     } 
    52     for (vector<int>::iterator it=vt.begin();it!=vt.end();it++) 
    53     {
    54         ans[*it]=0;
    55     }
    56     for (int i=1;i<=n;i++)
    57         printf("%d
    ",ans[i]);
    58     return 0;
    59 }

    其实上面的代码就用到了单调栈的思想

    何为单调栈?
    解释一下:
    单调栈类似单调队列,这道题中要运用到单调栈。
    如下:
    令f[i]为向右看齐的人的标号
    6 3 2 6 1 1 2
    f分别为 3 3 0 6 6 0
    首先,最后一个人必然没有向右看齐的人的编号
    先将最右边的人加入栈
    接着,我们发现1,1比2小,先加入栈,当前f值为6
    接着,又来了一个1,发现1=1,弹出1,接着发现1<2,则将1加进栈,当前f值为6
    接着,来了一个6,6>2,弹出2,当前f值为0
    接着,来了一个2,2<6,加入2,当前f值为3
    最后,来了一个3,3>2,弹出2,将3加入栈,当前f值为3
    最后的栈中有3和6
    最后的答案就是3 3 0 6 6 0
    每次只在栈中存数字标号,进来一个数,就把小于等于他的数全部弹出,若剩下有数,则答案是剩下的数,否则答案是0
    为什么?
    因为:
    若x小于当前数,x不会成为答案。
    这就是单调栈的用法

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <iostream>
     4 #include <string>
     5 #include <math.h>
     6 #include <algorithm>
     7 #include <vector>
     8 #include <stack>
     9 #include <queue>
    10 #include <set>
    11 #include <map>
    12 #include <math.h>
    13 const int INF=0x3f3f3f3f;
    14 typedef long long LL;
    15 const int mod=1e9+7;
    16 const int maxn=1e5+10;
    17 using namespace std;
    18 
    19 int A[maxn]; 
    20 int ans[maxn];
    21 stack<int> sk; 
    22 
    23 int main()
    24 {
    25     int n;
    26     scanf("%d",&n);
    27     for (int i=1;i<=n;i++)
    28         scanf("%d",&A[i]);
    29     for(int i=n;i>=1;i--)
    30     {
    31         while(!sk.empty()&&A[sk.top()]<=A[i])
    32             sk.pop();
    33         if(!sk.empty())
    34             ans[i]=sk.top();
    35         else
    36             ans[i]=0;
    37         sk.push(i);
    38     }
    39     for (int i=1;i<=n;i++)
    40         printf("%d
    ",ans[i]);
    41     return 0;
    42 }
  • 相关阅读:
    Codeforces 798C
    Codeforces 777E
    Codeforces 801C Voltage Keepsake(二分枚举+浮点(模板))
    【NOIP 2017】宝藏
    利普希茨
    【NOIP2008】双栈排序
    捕老鼠
    失格
    【JZOJ4307】喝喝喝
    Blocks
  • 原文地址:https://www.cnblogs.com/jiamian/p/11495076.html
Copyright © 2011-2022 走看看