CodeForces 573B Bear and Blocks

题意

题意不好写,就略过了。

( exttt{Data Range}:1leq nleq 10^5,1leq h_ileq 10^9)

题解

这神仙题差点把我给卡死。

首先考虑一次操作会对第 (i) 列方块的高度有什么影响,分三种情况讨论一下:

  • 如果这列方块比左边一列的方块高,那么高度变为 (h_{i-1})

  • 如果这列方块比右边一列的方块高,那么高度变为 (h_{i+1})

  • 否则最上面一个方块总是要被消去的,高度变为 (h_{i}-1)

三种情况取个最小值得到 (h_i=min(h_{i-1},h_{i+1},h_i-1))

接下来考虑两次操作对 (h_i) 的影响,我们先算出 (h_{i-1},h_i,h_{i+1}) 一次操作后的高度,分别为:

[h_{i-1}=min(h_{i-2},h_{i},h_{i-1}-1),h_i=min(h_{i-1},h_{i+1},h_i-1),h_{i+1}=min(h_{i},h_{i+2},h_{i+1}-1) ]

再套一遍公式我们得到:

[h_i=min(h_{i-2},h_{i-1}-1,h_i-2,h_{i+1}-1,h_{i+2}) ]

利用数学归纳法我们知道 (k) 次操作后有

[h_{i}=min(h_{i-k},h_{i-k+1}-1,cdots,h_{i}-k,cdots,h_{i+k}) ]

于是我们的目标就是要求出对于每个 (i) 使得 (h_{i}=0) 的最小的 (k) 的最大值。

接下来我们单独考虑某个 (h_i),然后记 (k_j) 表示由 (h_j) 算出来的 (k) 值。

对于 (jin[i-k,i]) 来说 (h_i=h_j-j+i-k_j),即 (k_j=h_j-j+i)

同理得到对于 (jin[i,i+k]) 来说 (k_j=h_j+j-i)

由于现在 (i) 是恒定的,所以我们只需要求出 (h_j-j) 的前缀最小值和 (h_j+j) 的后缀最小值即可。这个可以使用线段树搞出来,注意几个小细节就好了。

代码

#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=2e5+51,inf=0x3f3f3f3f; 
struct SegmentTree{
    ll l,r,mn,mn2;
};
SegmentTree tree[MAXN<<2];
ll n,res=-inf;
ll h[MAXN];
inline ll read()
{
    register ll num=0,neg=1;
    register char ch=getchar();
    while(!isdigit(ch)&&ch!='-')
    {
        ch=getchar();
    }
    if(ch=='-')
    {
        neg=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        num=(num<<3)+(num<<1)+(ch-'0');
        ch=getchar();
    }
    return num*neg;
}
#define ls node<<1
#define rs (node<<1)|1
inline void update(ll node)
{
    tree[node].mn=min(tree[ls].mn,tree[rs].mn);
    tree[node].mn2=min(tree[ls].mn2,tree[rs].mn2);
}
inline void create(ll l,ll r,ll node)
{
    tree[node]=(SegmentTree){l,r,0,0};
    if(l==r)
    {
        return (void)(tree[node].mn=h[l]-l,tree[node].mn2=h[l]+l);
    }
    ll mid=(l+r)>>1;
    create(l,mid,ls),create(mid+1,r,rs),update(node);
}
inline ll query(ll l,ll r,ll node)
{
    if(l>r)
    {
        return inf;
    }
    if(l<=tree[node].l&&r>=tree[node].r)
    {
        return tree[node].mn;
    }
    ll mid=(tree[node].l+tree[node].r)>>1;
    return min(l<=mid?query(l,r,ls):inf,r>mid?query(l,r,rs):inf);
}
inline ll query2(ll l,ll r,ll node)
{
    if(l>r)
    {
        return inf;
    }
    if(l<=tree[node].l&&r>=tree[node].r)
    {
        return tree[node].mn2;
    }
    ll mid=(tree[node].l+tree[node].r)>>1;
    return min(l<=mid?query2(l,r,ls):inf,r>mid?query2(l,r,rs):inf);
}
#undef ls
#undef rs
int main()
{
    n=read();
    for(register int i=1;i<=n;i++)
    {
        h[i]=read();
    }
    create(0,n+1,1);
    for(register int i=0;i<=n+1;i++)
    {
        res=max(res,min(query(0,i,1)+i,query2(i,n+1,1)-i));
    }
    printf("%d
",res);
}
原文地址:https://www.cnblogs.com/Karry5307/p/13584641.html