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