zoukankan      html  css  js  c++  java
  • 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);
    }
    
  • 相关阅读:
    【转】C#字符串替换_无视大小写
    如何安装inf文件
    IDisposable模式
    VS2005 模板的制作方法
    ASP.NET Client Side State Management
    微软提供正确卸载IE7的方法并恢复IE6!!!!
    Access JavaScript variables on PostBack using ASP.NET Code
    Windows Mobile 5.0 SDK R2 for Pocket PC安装错误解决方案
    Oracle日期函数与应用
    XP下安装IIS6.0的办法
  • 原文地址:https://www.cnblogs.com/Karry5307/p/13584641.html
Copyright © 2011-2022 走看看