Codeforces Round #305 (Div. 1)B - Mike and Feet 线段树

本文介绍了一道关于计算最大熊群力量的问题,并提供了两种解决方案。一种利用了线段树和集合进行动态更新,另一种使用栈来简化计算过程。

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

B. Mike and Feet
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard 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 from1 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 that1 ≤ x ≤ n the maximum strength among all groups of sizex.

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.

Sample test(s)
Input
10
1 2 3 4 5 4 3 2 1 6
Output
6 4 4 3 3 2 2 1 1 1 


题意:对于长度为x的子序列,每个序列的score为这个序列中的最小值,输出长度为x 的子序列的最大值

思路:首先按照值排序,按照从小到大的顺序添加到set中,对于新添加的数,如果他在set中的两边的位置分别为l,r的话,那么他可以修改长度小于r-l-1的子序列的score,使它们变大,线段树维护长度为x的子序列的score的最大值

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=200010;
int N;
struct node
{
    int x,id;
    bool operator<(const node &a)const
    {
        return x<a.x;
    }
}a[maxn];
set<int> mp;
set<int>::iterator it;
int ans[maxn];
struct IntervalTree
{
    int maxv[maxn<<2];
    int setv[maxn<<2];
    void build(int o,int l,int r)
    {
        maxv[o]=setv[o]=0;
        if(l==r)return ;
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build(o<<1,mid+1,r);
    }
    void update(int o,int l,int r,int q1,int q2,int x)
    {
        if(q1<=l&&r<=q2)
        {
            setv[o]=x;
            maxv[o]=x;
            return ;
        }
        pushdown(o);
        int mid=(l+r)>>1;
        if(q1<=mid)update(o<<1,l,mid,q1,q2,x);
        if(q2>mid)update(o<<1|1,mid+1,r,q1,q2,x);
    }
    void pushdown(int o)
    {
        if(setv[o])
        {
            setv[o<<1]=setv[o<<1|1]=setv[o];
            maxv[o<<1]=maxv[o<<1|1]=setv[o];
            setv[o]=0;
        }
    }
    int query(int o,int l,int r,int x)
    {
        if(l==r)return maxv[o];
        pushdown(o);
        int mid=(l+r)>>1;
        if(x<=mid)return query(o<<1,l,mid,x);
        return query(o<<1|1,mid+1,r,x);
    }
}tree;
int main()
{
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
    {
        scanf("%d",&a[i].x);
        a[i].id=i;
    }
    sort(a+1,a+1+N);
   
    mp.insert(0);mp.insert(N+1);
    int l,r;
    tree.build(1,1,N);
    for(int i=1;i<=N;i++)
    {
        it=mp.lower_bound(a[i].id);
        r=*it;it--;l=*it;
        if(r-l-1>=1)tree.update(1,1,N,1,r-l-1,a[i].x);
        mp.insert(a[i].id);
    }
    for(int i=1;i<=N;i++)
        ans[i]=tree.query(1,1,N,i);
    for(int i=1;i<=N;i++)
        printf("%d ",ans[i]);
    printf("\n");
    return 0;
}

还可以用更简单的方法(下面的代码转自codeforces):

#include <bits/stdc++.h>
using namespace std;
template <typename T> bool maxup(T &a, const T &b) { return a < b ? (a = b, true) : false; }
template <typename T> bool minup(T &a, const T &b) { return a > b ? (a = b, true) : false; }

const int MAX = 200100;
int n;
int a[MAX], low[MAX], high[MAX], m[MAX];

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    stack<int> up;
    up.push(0);
    for (int i = 1; i <= n; i++) {
        while (a[i] <= a[up.top()])
            up.pop();
        low[i] = up.top();
        up.push(i);
    }
    up = stack<int>();
    up.push(n + 1);
    for (int i = n; i > 0; i--) {
        while (a[i] <= a[up.top()])
            up.pop();
        high[i] = up.top();
        up.push(i);
    }
    for (int i = 1; i <= n; i++)
        maxup(m[high[i] - low[i] - 1], a[i]);
    for (int i = n - 1; i >= 1; i--)
        maxup(m[i], m[i + 1]);
    for (int i = 1; i <= n; i++)
        printf("%d ", m[i]);
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值