Luogu P6047 丝之割
一道简单的斜率优化 dp。
Solution
当选择二元组 \((p,q)\) 时,对于满足 \(i>p,j<q\) 的弦 \((i,j)\):若存在弦 \((i',j')\) 满足 \(i'>i,j'<j\),在破坏弦 \((i,j)\) 时一定会破坏弦 \((i',j')\),故先删去所有的弦 \((i',j')\)。
在排序后,由于弦的上坐标和下坐标分别都单调递增,考虑 dp 分划阶段。
令 \(c_i=\min\limits_{k=1}^{i} a_i,d_i=\min\limits_{k=i}^{n} b_i\),容易得到状态转移方程:
\[dp_i=\min_{j<i} \{dp_j+c_{u_{j+1}-1}d_{v_{i-1}}\}
\]
考虑斜率优化。将式子转化为 \(y=kx+b\) 的形式,有:
\[\begin{cases}
x=-c_{u_{j+1}-1} \\
y=dp_j \\
k=d_{v_{i-1}} \\
b=dp_i
\end{cases}\]
按照常规斜率优化 dp 套路,单调队列维护凸包斜率即可。
Code
/* ChongYun */
#include<bits/stdc++.h>
#define START_LL 1
using namespace std;
#define fir first
#define sec second
#define pii pair<int,int>
#define start(x) using namespace x
#if START_LL
#define int long long
#endif
#define ldb long double
namespace IO{
#define flush() fwrite(obuf,1,O-obuf,stdout)
#define putchar(x) ((O==obuf+(1<<21))&&(flush(),O=obuf)),*O++=x
char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read(){
register int x=0,f=1;
register char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
inline void write(int x){
if(x>9) write(x/10);
putchar((x%10)^48);
return ;
}
struct Flush{ ~Flush(){flush();} }_;
}start(IO);
const int N=3e5+5,inf=1e18;
int n,k,a[N],b[N],c[N],d[N];
int q[N],hd=1,tl=0,dp[N];
pii Rhy[N],Mil[N];
bool cmp(pii pt,pii qt){
if(pt.fir==qt.fir) return pt.sec<qt.sec;
return pt.fir<qt.fir;
}
ldb getx(int qwq){ return a[Mil[qwq+1].fir-1]; }
ldb gety(int qwq){ return dp[qwq]; }
ldb Slope(int qwq,int qaq){
if(getx(qwq)==getx(qaq)) return inf;
return -(gety(qwq)-gety(qaq))/(getx(qwq)-getx(qaq));
}
signed main(){
n=read(); k=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) b[i]=read();
for(int i=1;i<=k;i++){
Rhy[i].fir=read();
Rhy[i].sec=read();
}
sort(Rhy+1,Rhy+k+1,cmp);
int now=n; n=1;
int l=Rhy[1].fir,r=Rhy[1].sec;
Mil[1]=Rhy[1];
for(int i=2;i<=k;i++){
if(l<=Rhy[i].fir&&Rhy[i].sec<=r) continue;
l=Rhy[i].fir,r=Rhy[i].sec;
Mil[++n]=Rhy[i];
}
k=now;
a[0]=b[k+1]=inf;
for(int i=1;i<=k;i++) a[i]=min(a[i],a[i-1]);
for(int i=k;i>=0;i--) b[i]=min(b[i],b[i+1]);
q[++tl]=0;
for(int i=1;i<=n;i++){
while(hd<tl&&Slope(q[hd],q[hd+1])<=b[Mil[i].sec+1]) ++hd;
dp[i]=dp[q[hd]]+a[Mil[q[hd]+1].fir-1]*b[Mil[i].sec+1];
while(hd<tl&&Slope(q[tl],q[tl-1])>=Slope(i,q[tl])) --tl;
q[++tl]=i;
}
printf("%lld\n",dp[n]);
return 0;
}

浙公网安备 33010602011771号