CF1604A Era 题解
不愧是数学场……
题意
有 \(t\) 组数据,每组数据中包含一个 \(n\) 以及一个包含 \(n\) 个元素的序列 \(a\),请在这个序列中添加一些数使得对于每一个原始元素以及加入的元素都存在 \(a_i\leqslant i\)。输出至少需要加多少数达到目标。
数据范围:\(1\leqslant T\leqslant 200\),\(1\leqslant n\leqslant 100\)。
思路
考虑贪心地做这个事情。
对于每一个 \(a_i>i\),在 \(a_{i-1}\) 和 \(a_i\) 之间添加大量的 \(1\)(\(1\) 在任何位置都可以满足 \(a_i\leqslant i\)),为了保证最少,\(1\) 添加的个数应当是 \(a_i-i\) 个。
注意每次判断之前需要给这个数所在的位置后移前面加的 \(1\) 的个数位。
很容易证明,既然每次都使用最小的加数量使得 \(a_i\leqslant i\),满足最优子结构的性质,最终的答案一定也是最小值。
代码
非常易于理解。
struct node{
int val,add;//分别是数值和所在位置
} a[105];
void solve(){
cin>>n;
int sum=0;//sum表示到目前位置加的1的个数
for(int i=1;i<=n;i++){
cin>>a[i].val;
a[i].add=i;//初始化
}
for(int i=1;i<=n;i++){
a[i].add+=sum;//后移位置
if(a[i].val>a[i].add){//如果不满足
sum+=a[i].val-a[i].add;//暴力怎么做?加1!加1!加1!
}
}
cout<<sum<<endl;//输出加的1的个数即可
}