題解 CF1107G 【Vasya and Maximum Profit】
推銷 膜 zhouakngyang 寶典
\(\color{black}{\texttt {z}}\color{red}{\texttt {houakngyang}}\) AK 完比賽讓我來做這題。
題解:
為了方便,直接把 \(d_i\) 設為輸入的 \((d_{i+1}-d_i)^2\)。
直接做看不出啥我太菜了 ,只好先表示答案
\[ ans=max\{a\times (r-l+1) -\sum_{i=l}^{r}c_i-\max_{i=l}^{r-1}\{d_i\} \} \]
請注意 \(\max_{i=l}^{r-1}\{d_i\}\) 的 \(r-1\)
顯然的加一個字首和,設 \(sc_i=\sum\limits_{j=1}^{i}c_j\)
\[ans=max\{a\times (r-l+1) -sc_{r}-sc_{l-1}-\max_{i=l}^{r-1}\{d_i\} \} \]
然後就自閉了 \(5min\)
無聊變換一下式子,
\[ans=max\{(a\times r -sc_r)-(a\times (l-1)-sc_{l-1})-\max_{i=l}^{r-1}\{d_i\} \} \]
發現除了那個 \(\max_{i=l}^{r-1}\{d_i\}\) 都很好處理,啥都能維護的亞子。
不好處理就列舉唄。
列舉以 \(d_i\) 為最大值的區間 \([lp_i,rp_i]\) ,這個可以單調棧 \(O(n)\) 搞。
由於要保證 \(i\in [l,r]\) ,那麼\(l\) 一定在 \([lp_i,i]\) 內,\(r\) 在 \([i,rp_i]\) 內。然後直接用一個可以處理靜態詢問區間最大值的資料結構維護一下 \(a*i-sc_i\) 即可,注意下標!
還有一種情況不需要減 \(d_i\) ,就是 \(l=r\) 的時候,列舉特判一下即可
#define int long long inline int rd() { int a=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))a=a*10+(ch^48),ch=getchar(); return a*f; } #define N 300009 int n,a,ans; int c[N],sc[N],d[N]; int lg[N],pw2[25]; int st[N],top,lp[N],rp[N]; struct ST_Table { int st[20][N]; void init() { for(int i=1;i<=19;++i) for(int j=1;j+pw2[i]-1<=n;++j) st[i][j]=max(st[i-1][j],st[i-1][j+pw2[i-1]]); } int ask(int l,int r) { if(l>r)return 0; int x=lg[r-l+1]; return max(st[x][l],st[x][r-pw2[x]+1]); } }s[2]; void st_init() { lg[0]=-1,pw2[0]=1; for(int i=1;i<N;++i)lg[i]=lg[i>>1]+1; for(int i=1;i<=20;++i)pw2[i]=pw2[i-1]<<1; } signed main() { n=rd(),a=rd(); st_init(); for(int i=1;i<=n;++i)d[i]=rd(),sc[i]=sc[i-1]+(c[i]=rd()); for(int i=1;i<n;++i)d[i]=(d[i+1]-d[i])*(d[i+1]-d[i]); for(int i=1;i<n;++i) { while(top&&d[st[top]]<d[i])rp[st[top--]]=i-1; lp[i]=st[top]+1,st[++top]=i; } while(top)rp[st[top--]]=n-1; for(int i=1;i<=n;++i) s[0].st[0][i]=sc[i-1]-a*(i-1), s[1].st[0][i]=a*(i+1)-sc[i+1]; s[0].init(),s[1].init(); for(int i=1;i<=n;++i)ans=max(ans,a-c[i]); for(int i=1;i<n;++i) ans=max(ans,s[0].ask(lp[i],i)+s[1].ask(i,rp[i])-d[i]); printf("%lld\n",ans); return 0; }