1. 程式人生 > >Gym - 101806R :Recipe(分治+斜率優化)

Gym - 101806R :Recipe(分治+斜率優化)

rep pri cond return fin make n) rst style

#include<bits/stdc++.h>
#define pii pair<ll,int>
#define mp make_pair
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=300010;
const int inf=1e9;
ll dp[maxn],F[maxn],C[maxn],L[maxn];
pii a[maxn],b[maxn]; int q[maxn],top;
ll getans(
int p,int k) { return dp[k]+C[p]*F[k+1]-C[p]*p; } void update(int p) { if(top==0) return;int L=1,R=top-1,Mid; dp[p]=max(dp[p],getans(p,q[top])); while(L<=R){ Mid=(L+R)>>1; ll tmp1=getans(p,q[Mid]),tmp2=getans(p,q[Mid+1]); if(tmp1>tmp2) R=Mid-1
,dp[p]=max(dp[p],tmp1); else L=Mid+1,dp[p]=max(dp[p],tmp2); } } bool check(int p){ return (dp[p]-dp[q[top]])*(F[p+1]-F[q[top-1]+1])<= (dp[p]-dp[q[top-1]])*(F[p+1]-F[q[top]+1]); } void add(int p) { if(dp[p]==-inf) return ; if(top>0&&F[p+1]==F[q[top]+1
]&&dp[p]>dp[q[top]]) top--; while(top>1&&check(p)) top--; q[++top]=p; } void solve(int Le,int Ri) { if(Le==Ri) return ; int Mid=(Le+Ri)>>1; solve(Le,Mid); int tot1=0,tot2=0; top=0; rep(i,Le,Mid) a[++tot1]=mp(F[i+1],i); rep(i,Mid+1,Ri) b[++tot2]=mp(L[i],i); sort(a+1,a+tot1+1); sort(b+1,b+tot2+1); reverse(a+1,a+tot1+1); reverse(b+1,b+tot2+1); for(int i=1,j=1;i<=tot2;i++){ while(j<=tot1&&b[i].first<=a[j].first){ add(a[j].second); j++; } update(b[i].second); } solve(Mid+1,Ri); } int main() { int N; scanf("%d",&N); rep(i,1,N) scanf("%lld",&F[i]),F[i]+=i; rep(i,1,N) scanf("%lld",&C[i]); rep(i,1,N) scanf("%lld",&L[i]),L[i]+=i; rep(i,1,N) dp[i]=-inf; solve(0,N); if(dp[N]==-inf) puts("Impossible"); else printf("%lld\n",dp[N]); return 0; }

Gym - 101806R :Recipe(分治+斜率優化)