• DTOJ #2596. Greenhouse Growth


    【题目描述】

    你从计算机科学转向农业,你的新工作包括在一个地下温室种植向日葵。在温室中有 $ 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

    【数据范围与提示】

    对于所有数据,$ 1leq 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])," 
    "[j==n]);
        return 0;
    }
  • 相关阅读:
    usaco 1.11
    当数组时全局变量时。。。怎样进行循环初始化
    hdu 1097 用到了位的移动
    hdu 1006
    HNOI2008]神奇的国度
    App测试基本流程详解(汇总整理)
    IOS测试Fastmonkey
    pytest+allure2+jenkins环境部署
    如何在cmd查看文件内容的md5值
    软件测试学习linux基础
  • 原文地址:https://www.cnblogs.com/RenSheYu/p/11371593.html
Copyright © 2020-2023  润新知