题目链接.
算法思想
对于整数D而言,意思是发生苹果掉落的苹果树的棵树,注意同一棵苹果树只要掉了一个苹果就得算进去,但是掉了再多也只能算一棵。难点在计算E,好好按照题目给的表达式来计算
即对于任意一颗树A_i,它以及它的左右相邻两棵都掉落过苹果,就算进去一组。
代码解析
所有树组成一个环,我把它们拉直,成为一条线,用线性表(数组)存起来,为了表示环的特性,特意在一头一尾补充上其相邻的那棵树,巧妙地利用了drop[0], drop[N+1]这两个位置,详细见下面代码。
#include<iostream>
using namespace std;
long long int N, m;
long long int T = 0, D = 0, E = 0;
long long int apple_initial = 0, apple_end = 0, apple = 0;
//apple_initial 初始苹果数,apple_cut 疏果数(cut < 0), apple_end 最后剩余苹果数
int drop[1000005] = { 0 };
int main()
{
long long int i;
scanf("%lld", &N);
for (i = 1; i <= N; i++)
{
scanf("%lld", &m);
//第一个数据为初始苹果数,直接读取
scanf("%lld", &apple_initial);
apple_end = apple_initial;
m--;
while (m--) //这样写比用 for 循环省事
{
scanf("%lld", &apple);
if (apple <= 0) //疏果//记住不要忽略了 apple = 0的情况
{
apple_end += apple;
}
else //重新统计
{
if (drop[i] == 0 && apple_end > apple)//有苹果掉落
{
D++; //若它掉落过了,应该只是算一棵
drop[i] = 1;//记录它掉落了
}
apple_end = apple;
}
}
T += apple_end;
}
//计算 E
drop[0] = drop[N];
drop[N + 1] = drop[1];
for (i = 1; i <= N; i++)
{
if (drop[i-1] && drop[i] && drop[i+1])
{
E++;
}
}
printf("%lld %lld %lld", T, D, E);
return 0;
}
结果分析
得分100分,用时250ms,空间使用2.538MB,时间复杂度为O(N)。