DTOJ #2596. Greenhouse Growth

生来就可爱ヽ(ⅴ<●) 提交于 2019-11-27 18:03:59

【题目描述】

你从计算机科学转向农业,你的新工作包括在一个地下温室种植向日葵。在温室中有 $ n $ 个排列在一条直线的向日葵植株,从左向右编号为 $ 1 $ 到 $ n $ 。有 $ A,B $ 两个照射器为向日葵的生长提供光和热,且照射器 $ A,B $ 分别放置在向日葵的左右两端。每天只有 $ 1 $ 个照射器被打开,使所有向日葵转向光源,并使部分向日葵生长。向日葵会生长当且仅当其朝向的相邻植株比它更高,其每天的生长高度为 $ 1 $ 厘米。请注意,一个植株的生长将使其背后的植株立刻开始生长。你将被给出向日葵的初始高度和接下来 $ m $ 天的光照计划,请计算所有向日葵最终的高度。

【输入格式】

第一行有 $ 2 $ 个整数 $ n $ 和 $ m $ ——植株数和天数。

接下来一行包括 $ n $ 个整数 $ h_1, h_2,… , h_n $ ——从左到右向日葵的初始高度。

接下来一行包括一个仅含字母 $ A/B $ 长度为 $ m $ 的字符串——从第一天开始的光照计划。

【输出格式】

$ n $ 个整数——从左到右每株向日葵最终的高度。

【样例】

样例输入
6 5
4 3 5 3 6 6
BABAA

样例输出
5 5 6 6 6 6

【数据范围与提示】

对于所有数据,$ 1\leq n, m  \leq 300 000, 1 \leq h_k \leq10^9  $。

【题解】

显然高度相同的一块可以压在一起思考。观察有一个性质:时间单调递增时,块数单调不升。因此可以用链表维护。

对于每一块,记录其左右是否高于该块,则可计算出该块任意时间(合并前)的高度以及合并的时间。在合并的时间记录下该块,一起处理即可。

效率 $O(n+m)$,细节较多可参见代码。

【代码】

#include<bits/stdc++.h>
inline int read ( void )
{
    int x=0;char ch;bool f=true;
    while ( !isdigit(ch=getchar()) ) if ( ch=='-' ) f=false;
    for ( x=ch^48;isdigit(ch=getchar()); ) x=(x<<1)+(x<<3)+(ch^48);
    return f ? x : -x ;
}
const int maxn=300000+10;
int T,ta[maxn],tb[maxn],h[maxn],n,m,tot;
int Hab[maxn],Ha[maxn],Hb[maxn],cnt;
char S[maxn];
struct edge { int v,nxt; } e[maxn*3];
struct section { int l,r,h,pre,nxt,t;bool fl,fr,del; } q[maxn];
inline void Add ( int &x,int y ) { e[++cnt].nxt=x;e[x=cnt].v=y; }
inline int query ( section p ) { return p.h+p.fl*(ta[T]-ta[p.t])+p.fr*(tb[T]-tb[p.t]); }
inline void modify ( section &p ) { p.fl=query(p)<query(q[p.pre]);p.fr=query(p)<query(q[p.nxt]); }
inline void merge ( int i ) ;
inline void update ( int i )
{
    section &A=q[i],&B=q[A.nxt];
    int x=query(A),y=query(B),z=abs(x-y);
    if ( !z ) merge(i);
    bool Fl=(x>y)^A.fl,Fr=(x<y)^B.fr;
    if ( Fl and Fr ) { if ( ta[T]+tb[T]+z<=m ) Add(Hab[ta[T]+tb[T]+z],i); }
    else if ( Fl ) { if ( ta[T]+z<=m ) Add(Ha[ta[T]+z],i); }
    else if ( Fr ) { if ( tb[T]+z<=m ) Add(Hb[tb[T]+z],i); }
}
inline void merge ( int i )
{
    section &A=q[i];
    if ( A.del or !A.nxt ) return;
    section &B=q[A.nxt];
    int x=query(A),y=query(B);
    if ( x!=y ) return;
    B.del=1;A.r=B.r;A.nxt=B.nxt;
    if ( B.nxt ) q[B.nxt].pre=i;
    A.t=T;A.h=x;modify(A);
    if ( A.pre ) update(A.pre);
    if ( A.nxt ) update(i);
}
signed main()
{
    n=read();m=read();
    for ( int i=1;i<=n;i++ ) h[i]=read();
    for ( int i=1,j;i<=n;i=j+1 )
    {
        j=i;
        while ( j<n and h[j+1]==h[i] ) j++;
        q[++tot].l=i;q[tot].r=j;q[tot].h=h[i];
    }
    for ( int i=2;i<=tot;i++ ) q[i].pre=i-1;
    for ( int i=1;i<tot;i++ ) q[i].nxt=i+1;
    for ( int i=1;i<=tot;i++ ) modify(q[i]);
    for ( int i=1;i<tot;i++ ) update(i);
    scanf(" %s",S+1);
    for ( T=1;T<=m;T++ )
    {
        ta[T]=ta[T-1]+(S[T]=='A');
        tb[T]=tb[T-1]+(S[T]=='B');
        for ( int i=Ha[ta[T]];i;i=e[i].nxt ) merge(e[i].v);Ha[ta[T]]=0;
        for ( int i=Hb[tb[T]];i;i=e[i].nxt ) merge(e[i].v);Hb[tb[T]]=0;
        for ( int i=Hab[T];i;i=e[i].nxt ) merge(e[i].v);
    }
    ta[T]=ta[T-1];tb[T]=tb[T-1];
    for ( int i=1;i<=tot;i++ ) if ( !q[i].del ) for ( int j=q[i].l;j<=q[i].r;j++ ) printf("%d%c",query(q[i])," \n"[j==n]);
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!