题解 CF955E 【Icicles】

VenusM1nT

2020-11-22 20:10:47

Solution

考虑在 $T$ 点释放声波,那么第 $i$ 个位置的冰锥会在 $f_T(i)=a_i+|T-i|$ 时刻之后落地,若存在最小的 $j$ 使得 $f_T(j)<j$,那么 Krakozyabra 会在 $j$ 时刻被挡住,然后再等到左侧冰锥落下。考虑到后面可能有冰锥更早落下,可以得到答案为 $$\max\{\min_{1\leq i<j}\{f_T(i)\},\min_{j\leq i\leq n}\{f_T(i)\}\}$$ 此时复杂度为 $\text{O}(n^2)$,考虑优化。将 $f_T$ 中的绝对值拆掉,分别为 $f_T(i)=a_i+T-i\ (i\leq T)$,$f_T(i)=a_i-T+i\ (i>T)$,用两个数组 $\text{pre,\ suf}$ 存储。考虑转化 $f_T(i)<i$ 这个不等式,根据前面提到的拆绝对值,若 $i\leq T$,即为 $T<i\times 2-a_i$;若 $i>T$,即为 $a_i<T$。至此,可以通过枚举 $T$,二分 $i$,配合任意一种 rmq 算法得到答案。 ```cpp #include<bits/stdc++.h> #define N 100000 #define reg register #define inl inline #define inf 1e9 using namespace std; int n,a[N+5],_[N+5],minx[N+5][25],pre[N+5][25],suf[N+5][25]; inl int Query(reg int l,reg int r) { if(l>r) return inf; reg int k=_[r-l+1]; return min(minx[l][k],minx[r-(1<<k)+1][k]); } inl int QryP(reg int l,reg int r) { if(l>r) return inf; reg int k=_[r-l+1]; return min(pre[l][k],pre[r-(1<<k)+1][k]); } inl int QryS(reg int l,reg int r) { if(l>r) return inf; reg int k=_[r-l+1]; return min(suf[l][k],suf[r-(1<<k)+1][k]); } int main() { scanf("%d",&n); for(reg int i=1;i<=n;i++) { scanf("%d",&a[i]); minx[i][0]=a[i]; pre[i][0]=a[i]-i; suf[i][0]=a[i]+i; } for(reg int i=2;i<=n;i++) _[i]=_[i>>1]+1; for(reg int j=1;j<=20;j++) { for(reg int i=1;i<=n-(1<<j)+1;i++) { minx[i][j]=min(minx[i][j-1],minx[i+(1<<(j-1))][j-1]); pre[i][j]=min(pre[i][j-1],pre[i+(1<<(j-1))][j-1]); suf[i][j]=min(suf[i][j-1],suf[i+(1<<(j-1))][j-1]); } } reg int now=1,ans=inf; for(reg int i=1;i<=n;i++) { while(now<=i && now*2-a[now]<=i) now++; reg int x,y,pos=-1; if(now<=i) pos=now; else { reg int l=i,r=n; while(l<=r) { reg int mid=(l+r)>>1; if(Query(i,mid)<i) { pos=mid; r=mid-1; } else l=mid+1; } if(!~pos) continue; } if(pos<=i) { x=QryP(1,pos-1)+i; y=min(QryP(pos,i)+i,QryS(i+1,n)-i); } else { x=QryS(pos,n)-i; y=min(QryP(1,i)+i,QryS(i+1,pos-1)-i); } ans=min(ans,max(x,y)); } printf("%d\n",ans>=inf/2?-1:ans); return 0; } ```