贝茜是一头饥饿的牛。
每天晚上,如果牛棚中还有干草的话,贝茜都会吃掉其中的一捆。
初始时,牛棚中没有干草。
为了让贝茜不被饿死,农夫约翰制定了 N个给贝茜送干草的计划。
其中第 i个计划是在第 di 天的白天给贝茜送去 bi 捆干草。
这些计划互不冲突,保证 1≤d1<d2<…<dN≤T
输入样例1:
1 5
1 2
输出样例1:
2
样例1解释
两捆干草在第 1 天早上被送到了牛棚,所以贝茜第 1,2 天有干草吃。
输入样例2:
2 5
1 2
5 10
输出样例2:
3
样例2解释
两捆干草在第 1 天早上被送到了牛棚,所以贝茜第 1,2 天有干草吃。
10 捆干草在第 5 天早上被送到了牛棚,所以贝茜第 5 天有干草吃。
输入样例3:
2 5
1 10
5 10
输出样例3:
5
10捆干草在第 1天早上被送到了牛棚,所以贝茜第 1∼5 天都有干草吃。
思路:
这个问题的中心思想就是,把1 ~ t 这段天数看成一个线段,每个 di 天的时候给 bi 捆草,也就是说 di ~ di+bi 这个线段是有草吃的,那想要得到的结果就是在一个大线段中有许多这样的小线段,问大线段上被小线段覆盖过的整数点有多少个。
可以看到,题目中天数的数据范围是10的14次幂,所以说按照你的第一反应,有草吃的那天bool值为1,没草吃bool值为0,然后遍历一遍是行不通的。
注意到 d 的数量,即发草的天数是有限的,N范围内,那既然所有天数看不了,我们就看所有的 d 就好了,回到上面我们讲的思路,也就是每次都看小线段的起始点。我们用一个 k 表示之前的草最多可以吃到哪一天。因为开始 k=0 ,所以用一个 f 来特判一下是不是第一次。
如果 f == 0,说明是第一次,那要看 d 是不是1,是一的话说明第一天有草吃,那当前的草最多就可以吃到 k+b 天,以此更新k。如果d不是1,那说明 d 之前都是没草吃的,这里我们用 res 来记录没有草吃的天数。然后用d+b-1来更新 k 。
如果 f 不是 0 ,说明现在不是第一次发草,那就看 d 和 k 的大小来进行比较就行了,d 大于 k+1 的话说明k ~ d 这段时间没草吃,否则就是有草吃,不断更新 k 值就行了。
需要注意的是,在更新res 的时候,要注意看天数和 t 的关系。
代码:
#include<bits/stdc++.h>
using namespace std;int main(){long long int n , t;cin >> n >> t;long long int d;int b;long long int k = 0;int f = 0;int z = 0;long long int res = 0;for(int i = 0 ; i < n ; i++){cin >> d >> b;if(z == 1)break;if(f == 0){f = 1;if(d == 1){k = k + b;if(k >= t)z = 1;}else{if(d < t)res = res + d - 1;elseres = res + t , z = 1;k = d + b - 1;}}else{if(d > k+1){if(d <= t)res += d-k-1;elseres += t-k , z = 1;k = d + b - 1;}else{k = k + b;}}}// cout << res << "*** " << endl;if(z!=1 && k < t)res += t - k;cout << t - res << endl;return 0;
}