题目描述
科技
栈
分析
很容易想到要对每个重复的数进行操作,但如何操作呢?
容易想到:对每一个重复的树,我们贪心地为其寻找最近的一个空位,最后对操作距离排序,用最大距离和最小代价组合。
但遗憾的是:这是一个错解。
我们发现:
3 3 4 4 6 10
1 2 3 4 5 6
是一个反例,原因在于:代价不同,总移动距离相同时,应让最大的距离尽可能大,这样总代价才会尽可能小。
于是我们发现,对每一个空缺,应优先选择离其最近的没有地方放的数,这样,最大的数就会尽可能大。
这是一种先进后出的结构,于是,我们可以想到,用栈来模拟这一过程。
具体来说,我们用栈存储每一个有重复的数,对每一个空缺,为其填上栈顶元素,最后排序移动距离。
最后
a
n
s
=
∑
i
=
1
m
h
i
×
b
m
−
i
+
1
ans = \sum_{i = 1}^m h_i \times b_{m - i + 1}
ans=∑i=1mhi×bm−i+1
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1000006;
unsigned long long n,a[N],b[N],h[N],hz;
stack<unsigned long long>s;
int main()
{
scanf("%llu",&n);
for(unsigned long long i = 1;i <= n;i++)
scanf("%llu",&a[i]);
for(unsigned long long i = 1;i <= n;i++)
scanf("%llu",&b[i]);
unsigned long long tmp;
sort(a + 1,a + 1 + n);
for(unsigned long long i = 2;i <= n;i++) {
if(a[i - 1] == a[i])
s.push(a[i]);
for(int j = a[i - 1] + 1;j < a[i];j++) {
if(s.empty())
break;
tmp = s.top();
s.pop();
h[++hz] = j - tmp;
}
}
for(unsigned long long j = a[n] + 1;;j++) {
if(s.empty())
break;
tmp = s.top();
s.pop();
h[++hz] = j - tmp;
}
sort(h + 1,h + hz + 1);
sort(b + 1,b + n + 1);
unsigned long long ans = 0;
for(unsigned long long i = hz;i;i--)
ans = ans + h[i] * b[hz - i + 1];
printf("%llu\n",ans);
return 0;
}