昨天讲的概念和模板,今天讲一个差分序列的好题(好好体会里面的优化思想):
目录
题目:
思路:
题目:
手动打出样例哈
输入: 输出:
4 2
3 13
-2 -2 -2 36
3 33
10 4 7
4
4 -4 4 -4
5
1 -2 3 -4 5
思路:
先捋一下题意:给定长n的序列现有三种操作:问至少经过多少次操作才能把所有数都变成0。一共t次询问!
操作1,选一个数ai把1~i的数都减少1
操作2,选一个数ai把i~n的数都减少1
操作3,每个数都增加1
很明显要用差分序列来做,不过怎么使用差分序列很考思维和技巧
操作1:把dif[i+1]+1,dif[1]-1
操作2:把dif[i]-1
操作3:把dif[1]+1我们只需要对差分序列不断进行三个操作,直到变成全0即可
举个例子:原数列:1 -2 3 -4 5 对应制造差分:1,-3,5,-7,9
不难发现对于大于0的5,9需要减少,那就是执行操作2;对于小于0的-3,-7执行操作1即可;
然后只剩下dif[1]了,最后执行操作3就行了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int S=1<<18;
int a[S];
ll ans,dif[S];
void solve(){
ans=0;
int n;cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
dif[i]=a[i]-a[i-1];//制造差分序列
}
for(int i=2;i<=n;i++){
if(dif[i]>0)ans+=dif[i];//执行操作2
else {
int ab=-dif[i];
ans+=ab;//执行操作1
dif[1]-=ab;
}
}
ans+=abs(dif[1]);//执行操作3
cout<<ans<<'\n';
}
int main(){
int t;cin>>t;
while(t--) solve();
return 0;
}
综上:你是不是也发现我之前说的,“差分序列多于用数据的多次变动” 的意思了吧