P8632 题解
cppcppcpp3 · · 题解
传送门。
下文中所有出现的
设
暴力 dp 转移如下:
-
f_{i,1}=\sum\limits_{j=1}^i a_j(i-j) -
f_{i,2}=\min\limits_{1\le k<i}f_{k,1}+\sum\limits_{j=k+1}^i a_j(i-j) -
f_{i,3}=\min\limits_{1\le k<i}f_{k,2}+\sum\limits_{j=k+1}^i a_j(i-j)
答案
直接做是
可以把
-
f_{i,1}=i\times A_i-B_i -
f_{i,2}=\min\limits_{1\le k<i}f_{k,1}+i\times (A_i-A_k) - (B_i-B_k) -
f_{i,3}=\min\limits_{1\le k<i}f_{k,2}+i\times (A_i-A_k) - (B_i-B_k)
把只与
-
f_{i,2}-i\times A_i+B_i=-A_k \times i+(f_{k,1}+B_k) -
f_{i,3}-i\times A_i+B_i=-A_k \times i+(f_{k,2}+B_k)
将
注意
#include<bits/stdc++.h>
#define il inline
#define int long long
using namespace std;
const int N=1e6+5;
const int inf=1e18;
il int wrd(){
int x=0,f=1; char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1; c=getchar();}
while(isdigit(c)){x=x*10+c-48,c=getchar();}
return x*f;
}
int n,m,a[N],A[N],B[N],ans=inf,dp[N][4];
struct seg{
int k,b;
}sg1[N],sg2[N];
int val(int o,int x,bool op){
if(o==-1) return inf;
return op ? sg2[o].k*x+sg2[o].b : sg1[o].k*x+sg1[o].b;
}
int s[N<<2][2];
#define ls (t<<1)
#define rs (t<<1|1)
#define md ((l+r)>>1)
void modify(int l,int r,int t,int u,int op){
int &v=s[t][op];
if(val(v,md,op)>val(u,md,op)) swap(u,v);
if(val(v,l,op)>val(u,l,op)) modify(l,md,ls,u,op);
if(val(v,r,op)>val(u,r,op)) modify(md+1,r,rs,u,op);
}
int qry(int l,int r,int t,int x,int op){
int ans=val(s[t][op],x,op);
if(l==r) return ans;
return min(ans,x<=md ? qry(l,md,ls,x,op) : qry(md+1,r,rs,x,op));
}
signed main(){
m=wrd(),n=wrd();
while(m--){
int x=wrd(),y=wrd();
a[x]+=y;
}
A[0]=a[0];
for(int i=1;i<=n;++i) A[i]=A[i-1]+a[i],B[i]=B[i-1]+i*a[i];
sg1[0].b=sg2[0].b=inf;
for(int i=0;i<n;++i){
dp[i][1]=i*A[i]-B[i];
dp[i][2]=qry(0,n,1,i,0)+i*A[i]-B[i];
dp[i][3]=qry(0,n,1,i,1)+i*A[i]-B[i];
sg1[i]={-A[i],dp[i][1]+B[i]};
sg2[i]={-A[i],dp[i][2]+B[i]};
modify(0,n,1,i,0),modify(0,n,1,i,1);
ans=min(ans,dp[i][3]+n*(A[n]-A[i])-B[n]+B[i]);
}
return printf("%lld",ans),0;
}