1.本题例子
输入样例:
2 -1 3
输出样例:
6
使用去除细菌的农药,功率等级为 1,使用五次。然后使用添加细菌的农药,功率等级为 22,使用一次。
描述的时候是先后再前,但实际考虑应该为先前再后。因为农药的影响为以末尾开端的等差数列。
求 Farmer John 使用喷雾器的最少次数,使得每块草地都具有健康草的推荐细菌值,这里所描述的推荐细菌值为0.
如果我们从1~N,依次利用等差数列的性质,将所有数值计算为0。
5 1 3 -2 -7 5
将第一个数值1转换为0,我们可以看出来只需要转换一次,喷洒农药的浓度为5即可,浓度为5是由于它的位置决定的(从右到左第五个),那么它的值就成为了喷洒的次数,定义变量total为需要增减农药的次数,由于此次的喷洒会对之后的数值都会产生影响,这个影响我们可以进行统计,在对下一个值进行分析时,将影响加入,一起来分析,以此类推。
在考虑影响的时候,考虑之前的操作对本结点的影响:
1 | 3 | -2 | -7 | 5 | 喷洒一次细菌 | ||
影响前 | 0 | 3 | -2 | -7 | 5 | 对第二个值的影响为-2 | |
影响后 | 0 | 1 | -2 | -7 | 5 | 喷洒一次细菌 | |
影响前 | 0 | 1 | -2 | -7 | 5 | 对第三个值的影响不仅考虑这次的喷洒,之前喷洒的影响也要考虑 | |
影响后 | 0 | 0 | -2 | -7 | 5 | 对第三个值的影响为-3-2 | |
影响前 | 0 | 0 | -7 | -7 | 5 | 喷洒7次农药 | |
影响后 | 0 | 0 | 0 | 0 | 5 | 对第四个值的影响为-4-3+14 | |
影响前 | 0 | 0 | 0 | 0 | 5 | 对最后的值的影响为-5-4+21 | |
影响后 | 0 | 0 | 0 | 0 | 17 | 喷洒细菌17次 |
但是这样会超时。。。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
long long a[N];
int n;
long long b[N];
long long cnt,effect;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
long long total = a[i]+b[i];
if(total>0){
for(int j=i+1;j<=n;j++){
b[j]-= (j-i+1)*total;
}
cnt+=total;
}
else{
for(int j=i+1;j<=n;j++){
b[j]-=(j-i+1)*total;
}
cnt-=total;
}
/*for(int j=1;j<=n;j++){
cout<<b[j]<<' ';
}
cout<<endl;
for(int j=1;j<=n;j++){
cout<<a[j]+b[j]<<' ';
}
cout<<endl<<endl;*/
}
cout<<cnt;
return 0;
}
2.程序优化
超时说明O(n2)要降到O(n),从每次操作对后续的影响入手,发现每次影响的值为之前的操作次数,
5
1 3 -2 -7 5
第一个值的操作对后续的影响是线性的:2,3,4,5,我们也可以写成这样的形式:
1 | 3 | -2 | -7 | 5 | |
喷洒一次细菌的影响 | 0+1 | 1+1 | 1+1+1=2+1 | 1+1+1+1=3+1 | 1+1+1+1+1=4+1 |
我们可以看出来喷洒后的影响效果为1,而随着数组位置的增加,增加1的个数增多,如果我们将影响的结果存储起来,后面的数都增加这个影响就可以啦,我们定义cur_ops为根据当前的数值决定喷洒的次数,cnt_ops为之前总共需要影响的值,contribution为总共需要影响的值,ans为总共喷洒的次数。
contribution += cnt_ops;//在计算i位置的影响时,需要加上之前的影响
a[i] += contribution; //作用于i位置的影响生效
ll cur_ops = -a[i]; //根据影响后的值计算当前需要多少次喷洒
ans += abs(cur_ops); //统计喷洒次数
cnt_ops += cur_ops; //对后续结点的影响增加了
contribution += cur_ops; //将当前的喷洒影响增加到总影响当中,相当于1+1+。。。+1中的最后一个1.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios::sync_with_stdio(false); cin.tie(0);
int n; cin >> n;
vector<ll> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
ll ans = 0;
ll contribution = 0;
ll cnt_ops = 0;
for (int i = 0; i < n; i++) {
contribution += cnt_ops;
a[i] += contribution;
ll cur_ops = -a[i];
ans += abs(cur_ops);
cnt_ops += cur_ops;
contribution += cur_ops;
}
cout << ans << '\n';
}