链接
题解
注意出发时间可能是负数
对每只猫求出:要把这只猫带走,最早啥时候出发
所有的猫按照这个时间排序
然后就成了区间 d p dp dp
斜率优化感觉都忘得差不多了qwq,虽然 w a wa wa了无数遍不过最终还是过了
代码
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
ll c, f(1);
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-0x30;
return f*x;
}
ll n, m, d[maxn], sb[maxn], p, dp[105][100010], b[maxn];
pll cat[maxn];
bool ok(pll p1, pll p2, pll p3)
{
ll x1=p2.first-p1.first, y1=p2.second-p1.second, x2=p3.first-p2.first, y2=p3.second-p2.second;
return x1*y2-x2*y1 > 0;
}
ll cost(ll l, ll r)
{
ll ans=0, i;
// for(i=l;i<=r;i++)
// {
// ans+=b[r]+cat[i].first-cat[i].second;
// }
// return ans;
return (r-l+1)*b[r]-sb[r]+sb[l-1];
}
int main()
{
ll i, j;
n=read(), m=read(), p=read();
rep(i,n-1)d[i+1]=d[i]+read();
rep(i,m)
{
ll h=read(), t=read();
cat[i]=pll(d[h],t);
}
sort(cat+1,cat+m+1,[](pll x, pll y){return x.second-x.first < y.second-y.first;});
rep(i,m)b[i]=cat[i].second-cat[i].first;
rep(i,m)sb[i]=sb[i-1]+b[i];
rep(i,m)dp[1][i]=i*b[i]-sb[i];
dp[1][0]=0;
for(j=2;j<=p;j++)
{
auto g=dp[j-1], f=dp[j];
for(i=0;i<=m;i++)f[i]=linf;
deque<pll> q;
for(i=1;i<=m;i++)
{
pll pt(pll(i-1,g[i-1]+sb[i-1]));
while(q.size()>1 and !ok(q.at(q.size()-2),q.at(q.size()-1),pt))
q.pop_back();
q.emb(pt);
ll t=q.front().second-q.front().first*b[i];
while(q.size()>1 and t>q[1].second-q[1].first*b[i])
{
t=q[1].second-q[1].first*b[i];
q.pop_front();
}
f[i]=t+i*b[i]-sb[i];
}
}
cout<<dp[p][m];
return 0;
}