B-找山坡 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛)

这篇博客介绍了如何在广东工业大学第十五届文远知行杯程序设计竞赛中解决一个问题。给定一个数组,目标是找到两个相等值的坐标,使得它们之间的所有值都大于等于这两个坐标上的值,并求最大坐标差。博主使用线段树存储区间最小值,同时用映射记录每个元素最后一次出现的位置。通过遍历数组并检测区间最小值,博主成功实现了算法并找到了最大坐标差。
摘要由CSDN通过智能技术生成

B-找山坡 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛)

母牛哥在电脑面前坐久了,想站起来看看窗外的小山坡,于是就想出了这个问题:
给定一个大小为n的数组a,序号从1开始,
计算:
max{ R - L | 1 <= L <= R <= n, a[L] == a[R], 对于所有i (L <= i <= R), 满足a[i] >= a[L] }.
也就是找到两个坐标,这两个坐标的值相等,并且他们之间的值都大于等于这两个坐标上的值.
这两个坐标相减最大能是多少.

用线段树存区间最小值。

然后用map存某个数上一次出现的位置。

扫一遍输入数据,如果发现一个以前出现过的数,就用线段树检测区间最小值是否大于等于这个值。
如果是,则符合题意。
如果否,则将该数的上一个位置更新为此位置。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t[8000050];
ll cnt=0;
ll a[2000100];
ll n;
map <ll,ll> m;
void pushup(ll rt)
{
    t[rt]=min(t[rt<<1],t[rt<<1|1]);
}
void build(ll l=1,ll r=n,ll rt=1){
    if(l==r){
        cin>>t[rt];
        a[++cnt]=t[rt];
        return;
    }
    ll mid=(l+r)>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    pushup(rt);
}
ll query(ll ql,ll qr,ll l=1,ll r=n,ll rt=1)
{
    if(ql<=l&&r<=qr){
        return t[rt];
    }
    ll mid=(l+r)>>1;
    ll ans=2e9;
    if(mid>=ql){
        ans=min(query(ql,qr,l,mid,rt<<1),ans);
    }
    if(mid<qr){
        ans=min(query(ql,qr,mid+1,r,rt<<1|1),ans);
    }
    return ans;
}
int main()
{
    ll ans=0;
    cin>>n;
    for(ll i=0;i<=4*n;i++)
        t[i] = 1e9+10;
    build();
    for(ll i=1;i<=n;i++){
        if(m[a[i]]==0){
            m[a[i]]=i;
        }else{
            if(query(m[a[i]],i)>=a[i]){
                ans=max(ans,i-m[a[i]]);
            }else{
                m[a[i]]=i;  
            }
        }
    }
    cout<<ans;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值