Codeforces 320D Psychos in a Line【单调栈+Dp】

D. Psychos in a Line
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

There are n psychos standing in a line. Each psycho is assigned a unique integer from 1 to n. At each step every psycho who has an id greater than the psycho to his right (if exists) kills his right neighbor in the line. Note that a psycho might kill and get killed at the same step.

You're given the initial arrangement of the psychos in the line. Calculate how many steps are needed to the moment of time such, that nobody kills his neighbor after that moment. Look notes to understand the statement more precise.

Input

The first line of input contains integer n denoting the number of psychos, (1 ≤ n ≤ 105). In the second line there will be a list of n space separated distinct integers each in range 1 to n, inclusive — ids of the psychos in the line from left to right.

Output

Print the number of steps, so that the line remains the same afterward.

Examples
input
10
10 9 7 8 6 5 3 4 2 1
output
2
input
6
1 2 3 4 5 6
output
0
Note

In the first sample line of the psychos transforms as follows: [10 9 7 8 6 5 3 4 2 1]  →  [10 8 4]  →  [10]. So, there are two steps.


题目大意:

给出N个数,如果一个数的右边相邻的那个数小于当前数,那么他右边这个数就会被删除。

问会进行多少轮次这个游戏。


思路:


这个题写一个链表也可以,但是常数相对大一些。

这里写一下单调栈的思路:

我们模拟一下单调栈就能理解了。假设有样例:

5 6 3 7 4 1 2

①首先将5放入栈,设定其价值为0.表示这个点现在左边没有比他大的点,也就是这个点不需要操作。

②然后将6放入栈,同时需要先将5弹出栈,现在栈内情况为:(6)同时设定其价值为0.

③然后将3放放入栈,现在栈内情况为:(6,3),此时我们设定3的价值为0+1.

④然后将7放入栈,同时弹出3和6,设定7的价值为0,现在栈内的情况为:(7);

⑤然后将4放入栈,现在栈内情况为:(7,4),我们此时设定4的价值为0+1.

⑥然后将1放入栈,现在栈内情况为:(7,4,1),我们此时设定1的价值为1+1=2.

⑦最后将2放入栈,同时弹出1,现在栈内情况为:(7,4,2),我们此时设定2的价值为1+1=2.


价值最大为2,所以整体需要2次操作。

所以我们每次操作的时候,先将栈内老元素弹出,同时维护弹出的元素的最大价值(maxn),那么我们此时再加入栈内的元素的价值就是这个最大价值+1(maxn+1),表示我们这个当前数字操作的次数是要接着之前几个数进行的。如果没有弹出操作,那么对应maxn就是0.

过程维护一下即可。

具体内容参考代码。


Ac代码:


#include<stdio.h>
#include<string.h>
#include<stack>
using namespace std;
struct node
{
    int num,val;
}now,nex;
int a[150000];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        stack<node>s;
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            int sum=0;
            while(s.size()>0)
            {
                now=s.top();
                if(now.num<a[i])
                {
                    s.pop();
                    sum=max(sum,now.val);
                }
                else break;
            }
            now.num=a[i];now.val=sum+1;
            if(s.size()==0)now.val=0;
            ans=max(ans,now.val);
            s.push(now);
        }
        printf("%d\n",ans);
    }
}





单调栈是一种常用的数据结构,用于解决一类特定的问题,其中最常见的问题是找到数组中每个元素的下一个更大或更小的元素。在Codeforces编程竞赛中,单调栈经常被用于解决一些与数组相关的问题。 下面是单调栈的一般思路: 1. 创建一个空栈。 2. 从左到右遍历数组元素。 3. 对于每个元素,将其与栈顶元素进行比较。 - 如果当前元素小于等于栈顶元素,则将当前元素入栈。 - 如果当前元素大于栈顶元素,则将栈顶元素弹出,并将当前元素入栈。 4. 重复步骤3,直到遍历完所有元素。 这样,最后剩下的栈中元素就是没有下一个更大或更小元素的元素。在使用单调栈求解具体问题时,我们可以根据需要进行一些特定的操作。 例如,如果要找到一个数组中每个元素的下一个更大的元素,可以使用单调递减栈。具体操作如下: 1. 创建一个空栈和一个空结果数组。 2. 从左到右遍历数组元素。 3. 对于每个元素,将其与栈顶元素进行比较。 - 如果当前元素小于等于栈顶元素,则将当前元素入栈。 - 如果当前元素大于栈顶元素,则将栈顶元素弹出,并将其在结果数组中的位置记录为当前元素的下一个更大元素的索引。 4. 将当前元素入栈。 5. 重复步骤3和4,直到遍历完所有元素。 6. 结果数组中没有下一个更大元素的位置,可以设置为-1。 以下是一个使用单调递减栈求解下一个更大元素问题的示例代码: ```cpp #include <iostream> #include <stack> #include <vector> std::vector<int> nextGreaterElement(std::vector<int>& nums) { int n = nums.size(); std::vector<int> result(n, -1); std::stack<int> stack; for (int i = 0; i < n; i++) { while (!stack.empty() && nums[i] > nums[stack.top()]) { result[stack.top()] = i; stack.pop(); } stack.push(i); } return result; } int main() { std::vector<int> nums = {1,3, 2, 4, 5, 1}; std::vector<int> result = nextGreaterElement(nums); for (int i = 0; i < result.size(); i++) { std::cout << "Next greater element for " << nums[i] << ": "; if (result[i] != -1) { std::cout << nums[result[i]]; } else { std::cout << "None"; } std::cout << std::endl; } return 0; } ``` 以上代码将输出: ``` Next greater element for 1: 3 Next greater element for 3: 4 Next greater element for 2: 4 Next greater element for 4: 5 Next greater element for 5: None Next greater element for 1: None ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值