题目描述
你正在与n只怪兽作战。第i只怪兽有血量a[i],a[i]是整数。当a[i]<=0时,第i只怪兽死亡。你可以施展如下两种法术:
(1) 给某一只怪兽i造成一点伤害
(2) 给所有怪兽造成1点伤害,并且若在施展该法术后有怪兽死亡,会再次释放该法术。直到某一次释放后没有怪兽死亡为止。
造成一点伤害,怪兽的血量就会减少一点。法术1可以无限释放,法术2只能主动释放一次。请问杀死所有怪兽至少需要释放法术1多少次?0
输入
第一行一个整数t(1<=t<=10000)表示数据组数
每组数据包含两行,第一行一个整数n(1<=n<=200000),第二行n个整数a[i](1<=a[i]<=n)
数据保证所有的n的和不超过200000
输出
对于每组数据,输出一个整数表示至少释放多少次法术1
样例输入
2
3
3 1 2
6
4 1 5 4 1 1
样例输出
0
4
做法
粗说——这里只要判断一下a[i]+1是否能等于a[i+1],就说明能连续释放法术1,可以不计,或如果是a[i]=a[i+1]就说明使用法术1能每一个都减1,那就从0开始。
细说—— 相等的情况:
1
5
2 2 2 2 2
从0开始就可以把第1个减去1,就发现后面都不用变了。
因此,得出结论:
如果有n个相等数字,只要变动a[1]-1次就行了。
这是相等的情况。
不相等的情况:
1
5
1 2 4 5 6
(如果顺序是逆序,一定要sort)
我们就判断a[i]是否等于a[i+1]+1
加1代表能连续释放法术1,否则-(a[i+1]-a[i]-1)(为了提高速度)
以上就是两种情况。
代码(加了scanf和printf,否则超时)
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll T,n,i,a[200010],tot,sum;
int main() {
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
for(i=1; i<=n; i++)
scanf("%d",&a[i]);
sort(a+1,a+1+n);
sum=0;
for(i=0; i<n; i++)
if(a[i]!=a[i+1]&&a[i]+1!=a[i+1])
tot=(a[i+1]-a[i]-1),sum+=tot,a[i+1]-=tot;
printf("%d\n",sum);
}
}