Codeforces Round #305 (Div. 2) D 栈

本文介绍了一个有趣的问题:如何计算不同大小熊群的最大力量值。通过预处理找出每个熊可以成为最小值的有效范围,并利用栈来高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



链接:戳这里


D. Mike and Feet
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Mike is the president of country What-The-Fatherland. There are n bears living in this country besides Mike. All of them are standing in a line and they are numbered from 1 to n from left to right. i-th bear is exactly ai feet high.

A group of bears is a non-empty contiguous segment of the line. The size of a group is the number of bears in that group. The strength of a group is the minimum height of the bear in that group.

Mike is a curious to know for each x such that 1 ≤ x ≤ n the maximum strength among all groups of size x.

Input
The first line of input contains integer n (1 ≤ n ≤ 2 × 105), the number of bears.

The second line contains n integers separated by space, a1, a2, ..., an (1 ≤ ai ≤ 109), heights of bears.

Output
Print n integers in one line. For each x from 1 to n, print the maximum strength among all groups of size x.

Examples
input
10
1 2 3 4 5 4 3 2 1 6
output
6 4 4 3 3 2 2 1 1 1 

题意:
给出n个数,定义strength为连续的区间内最小的数,问长度x的(1<=x<=n)strength对应的最大值
也就是取一段区间内最小值最大

思路:
预处理出当前数ai能作为最小值的[l,r]区间
取出每个长度的最大值,如果该长度没有值,则至少比长度+1的大。直接赋值就可以了
怎么处理[l,r]区间呢?
先处理R区间,当前栈内存的是从左到右的值依次从小到大。当前值如果比栈首的小,说明栈首的值的R区间就只能到i-1了。同理处理L区间的时候从右往左,当前值ai如果比栈首的值小,当前栈首的L值为i+1

代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
using namespace std;
int n;
struct node{
    int pos,v;
    node(int pos=0,int v=0):pos(pos),v(v){}
};
stack<node> qu;
int a[200100];
int L[200100],R[200100];
int anw[200100];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    qu.push(node(0,0));
    node now;
    for(int i=1;i<=n;i++){
        while(!qu.empty()){
            now=qu.top();
            if(a[i]<now.v){
                R[now.pos]=i-1;
                qu.pop();
            } else {
                qu.push(node(i,a[i]));
                break;
            }
        }
    }
    while(!qu.empty()){
        now=qu.top();
        qu.pop();
        R[now.pos]=n;
    }
    ///for(int i=1;i<=n;i++) cout<<R[i]<<" "; cout<<endl;
    qu.push(node(0,0));
    for(int i=n;i>=1;i--){
        while(!qu.empty()){
            now=qu.top();
            if(a[i]<now.v){
                L[now.pos]=i+1;
                qu.pop();
            } else {
                qu.push(node(i,a[i]));
                break;
            }
        }
    }
    while(!qu.empty()){
        now=qu.top();
        qu.pop();
        L[now.pos]=1;
    }
    ///for(int i=1;i<=n;i++) cout<<L[i]<<" ";cout<<endl;
    for(int i=1;i<=n;i++){
        int len=R[i]-L[i]+1;
        anw[len]=max(anw[len],a[i]);
    }
    for(int i=n;i>=1;i--){
        if(anw[i]<anw[i+1]) anw[i]=anw[i+1];
    }
    for(int i=1;i<=n;i++) cout<<anw[i]<<" ";cout<<endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值