1. 程式人生 > >[Educational Round 59][Codeforces 1107G. Vasya and Maximum Profit]

[Educational Round 59][Codeforces 1107G. Vasya and Maximum Profit]

其中 如果 -c long long 分享 ide 成了 truct main

鹹魚了好久...出來冒個泡_(:з」∠)_

題目連接:1107G - Vasya and Maximum Profit

題目大意:給出\(n,a\)以及長度為\(n\)的數組\(c_i\)和長度為\(n\)的嚴格單調上升數組\(d_i\),求\(\max\limits_{1 \le l \le r \le n} (a\cdot(r-l+1)-\sum_{i=l}^{r}c_i-gap(l,r))\),其中\(gap(l, r) = \max\limits_{l \le i < r} (d_{i + 1} - d_i)^2\)

題解:首先將所有的\(c_i\)轉換為\(a-c_i\),這樣就變成了求\(\max\limits_{1 \le l \le r \le n} (\sum_{i=l}^{r}c_i-gap(l,r))\)。如果\(l,r\)確定的話,我們就能通過求前綴和以及區間內最大值來算出該區間對應的答案,但我們還需要進一步的優化。

  考慮每一個\(d_{i + 1} - d_i\)能成為\(gap(l,r)\)的範圍,即在區間\([L,R]\)中,\(\forall L \le l \le r \le R,gap(l,r)\le d_{i + 1} - d_i\)。這樣我們只需要用線段樹查詢區間\([L,R]\)的最大子段和就能求出當\(gap(l,r) \le d_{i + 1} - d_i\)時的答案。先預處理所有的\(L,R\),再掃一遍就好了。

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
#define N 300001
#define LL long long
LL n,b,l[N],r[N],a[N],d[N],L,R,M,S,ans;
struct rua{LL l,r,w,s,lw,rw;}t[N<<2]; void up(int x,int mid) { t[x].s=t[x*2].s+t[x*2+1].s; t[x].w=max(t[x*2].w,t[x*2+1].w); t[x].lw=max(t[x*2].lw,t[x*2].s+t[x*2+1].lw); t[x].rw=max(t[x*2+1].rw,t[x*2+1].s+t[x*2].rw); t[x].w=max(t[x].w,t[x*2].rw+t[x*2+1].lw); } void Build(int
l,int r,int x) { t[x].l=l,t[x].r=r; if(l==r){t[x].w=t[x].lw=t[x].rw=t[x].s=a[l];return;} int mid=l+r>>1; Build(l,mid,x*2); Build(mid+1,r,x*2+1); up(x,mid); } void ask(int ll,int rr,int l,int r,int x) { if(ll>r || l>rr)return; int mid=l+r>>1; if(ll<=l && r<=rr) { M=max(M,max(t[x].w,R+t[x].lw)); L=max(L,S+t[x].lw); R=max(R+t[x].s,t[x].rw); M=max(M,max(L,R)); S+=t[x].s; return; } ask(ll,rr,l,mid,x*2); ask(ll,rr,mid+1,r,x*2+1); } int main() { scanf("%I64d%I64d",&n,&b); for(LL i=1;i<=n;i++) { scanf("%I64d%I64d",&d[i],&a[i]); a[i]=b-a[i],ans=max(ans,a[i]); } for(LL i=n;i>=1;i--)d[i]-=d[i-1]; Build(1,n,1); d[1]=0; l[2]=2,r[n]=n; for(LL i=3;i<=n;i++) { LL _=i; while(_>2 && d[i]>=d[_-1]) _=l[_-1]; l[i]=_; } for(LL i=n-1;i>=2;i--) { LL _=i; while(_<n && d[i]>=d[_+1]) _=r[_+1]; r[i]=_; } for(LL i=2;i<=n;i++) { S=0; L=R=M=-(1e18); ask(l[i]-1,r[i],1,n,1); ans=max(ans,M-d[i]*d[i]); } printf("%I64d\n",ans); return 0; }
View Code

[Educational Round 59][Codeforces 1107G. Vasya and Maximum Profit]