CodeForces 573B Bear and Blocks

题意

题意不好写,就略过了。

\(\texttt{Data Range}:1\leq n\leq 10^5,1\leq h_i\leq 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\) 值。

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

同理得到对于 \(j\in[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\n",res);
}
posted @ 2020-08-30 10:50  Karry5307  阅读(147)  评论(1编辑  收藏  举报