AtCoder-abc228_h Histogram题解
题目大意
给定一段长度为\(n\)的数组\(a\)和\(c\),表示\(i\)的大小和将 \(a_i+1\) 的费用。如果最后剩\(k\)个不同的\(a_i\)就将费用加上 \(X\times k\)。
题目分析
首先该题想让我们的最后剩下的 \(a_i\) 个数最少,那我们就没必要创造新的 \(a_i\) 。所以最后的\(a_i\)序列一定是
\[a_{b_1},a_{b_1}···a_{b_1}|a_{b_2},a_{b_2}···a_{b_2}|a_{b_m},a_{b_m}···a_{b_m}
\]
即一段连续的\(a_i\)。
假设\(dp_i\)为以\(i\)为结尾的最小代价
先将\(a\)数组和\(c\)数组按\(a_i\)大小排序。建个结构体或\(\mathrm{pair}\)就行。这样后面就不用绝对值了。
\[dp_i \min \limits_{j=1}^{i}=\left(dp_{j-1}+\sum_{k=1}^{j}c_k(a_i-a_k)+X \right)
\]
\((a_i-a_k)\)这一项不好处理,所以把\(\sum\)拆开。
\[dp_i \min \limits_{j=1}^{i}=\left(dp_{j-1}+\sum_{k=1}^{j}c_k\times a_i-\sum_{k=1}^{j}c_k\times a_k+X \right)
\]
然后把\(\sum\)用前缀和替代。
设\(s1_i=\sum\limits_{j=1}^{i}c_j\)
\(s2_i=\sum\limits_{j=1}^{i}c_j\times a_j\)
\[dp_i \min \limits_{j=1}^{i}=\left(dp_{j-1}+a_i\times\left(s1_i-s1_{j-1}\right)-(s2_i-s2_{j-1})+X \right)
\]
然后这个式子看起来就很斜率优化。式子左边化简
\[dp_{j-1}+a_is1_i-a_is1_{j-1}-s2_i+s2_{j-1}+X
\]
我们考虑两个数\(j_1\)和\(j_2\)。当\(j_1\)比\(j_2\)更优势,式子为
\[dp_{j1-1}+a_is1_i-a_is1_{j1-1}-s2_i+s2_{j1-1}+X\le dp_{j2}+a_is1_i-a_is1_{j2-1}-s2_i+s2_{j2-1}+X
\]
消去不含\(j\)的项
\[dp_{j1-1}-a_is1_{j1-1}+s2_{j1-1}\le dp_{j2-1}-a_is1_{j2-1}+s2_{j2-1}
\]
移项
\[dp_{j1-1}-dp_{j2-1}+s2_{j1-1}-s2_{j2-1}\le a_is1_{j1-1}-a_is1_{j2-1}
\]
右边都有\(a_i\),合并一下
\[dp_{j1-1}-dp_{j2-1}+s2_{j1-1}-s2_{j2-1}\le a_i\left(s1_{j1-1}-s1_{j2-1}\right)
\]
把左边含有\(j\)的除到右边
\[\frac{dp_{j1-1}-dp_{j2-1}+s2_{j1-1}-s2_{j2-1}}{s1_{j1-1}-s1_{j2-1}}\le a_i
\]
然后调整一下
\[\frac{\left(dp_{j1-1}+s2_{j1-1}\right)-\left(dp_{j2-1}+s2_{j2-1}\right)}{s1_{j1-1}-s1_{j2-1}}\le a_i
\]
这样就行了。\(Y\)就是\(dp_{j-1}+s2_{j-1}\),\(X\)就是\(s1_{j-1}\)
然后就完事了
代码
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
#define int long long
typedef long double lb;
int n,xx;
const int N=2e5+10;
struct node{
int a,c;
}a[N];
bool cmp(node x,node y)
{
return x.a<y.a;
}
int q[N],dp[N],s1[N],s2[N];
lb X(int a)
{
return s1[a-1];
}
lb Y(int a)
{
return dp[a-1]+s2[a-1];
}
lb slope(int a,int b)
{
return (Y(a)-Y(b))/(X(a)-X(b));
}
int ans(int x,int y)
{
return dp[y-1]+a[x].a*(s1[x]-s1[y-1])-(s2[x]-s2[y-1])+xx;
}
signed main()
{
cin>>n>>xx;
for(int i=1;i<=n;i++)
{
cin>>a[i].a>>a[i].c;
}
sort(a+1,a+1+n,cmp);
int h=1,t=0;
for(int i=1;i<=n;i++)
{
s1[i]=s1[i-1]+a[i].c;
s2[i]=s2[i-1]+a[i].c*a[i].a;
}
for(int i=1;i<=n;i++)
{
while(h<t&&slope(i,q[t])<slope(q[t],q[t-1]))t--;
q[++t]=i;
while(h<t&&slope(q[h],q[h+1])<a[i].a)h++;
dp[i]=ans(i,q[h]);
}
cout<<dp[n];
}

浙公网安备 33010602011771号