一 阿里马马与四十大盗
1.题目
2.思路
1.回血只能一次性恢复完 —> 考虑贪心找到最后一次必须回血的位置
2.在最后一次必须回血的位置前的回血能回就回,因为最后都要回满的,所以早回晚回不影响选择的最优性
3.找最后一次回血的位置考虑后缀数组来判断
3.代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 7;
#define int long long
int n, m, a[N], p[N];
signed main(){
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
for(int i = n; i > 0; i--){
p[i] = p[i + 1] + a[i];
}
int now = m, res = 0;
for(int i = 2; i <= n; i++){
if(a[i] == 0){
res += m - now;
now = m;
}else{
now -= a[i];
if(now <= 0){
cout << "NO" << endl;
break;
}
}
if(now > p[i + 1]){
cout << res + n - 1 << endl;
break;
}
}
return 0;
}
二 烙饼
1.题目
2.思路
最少工作时间 ===> 保证每台烙饼机工作时间最长 ===> 即空闲时间最短
显然构造答案ans = max(mx(a[i]), (sum(a[i]) + m - 1)/m);
①mx(a[i]) > 平均烙饼时长:
一块饼不能分开烙,所以最短时间为mx(a[i]);
②mx(a[i]) <= 平均烙饼时长:
最短时间为烙饼时长,保证烙饼机空闲时间最短
烙饼序列从第一个烙饼机往后排就行,超过ans就分段给下一个烙饼机
3.代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 +10;
#define int long long
int n, m, a[N], res, sum;
int id1[N], id2[N], l[N], r[N], idx;
void add(int x, int y, int z, int d){
id1[idx] = x, id2[idx] = y;
l[idx] = z, r[idx] = d;
idx++;
}
signed main(){
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> a[i];
res = max(res, a[i]);
sum += a[i];
}
res = max(res, (sum + m - 1) / m);
int now = 0, in = 1;
for(int i = 1; i <= n; i++){
if(now + a[i] >= res){
add(i, in, now, res);
a[i] -= res - now;
in++; //下一台烙饼机
now = 0;
}
if(a[i] > 0){
add(i, in, now, now + a[i]);
now += a[i];
}
}
cout << idx << endl;
for(int i = 0; i < idx; i++){
cout << id1[i] << " " << id2[i] << " " << l[i] << " " << r[i] << endl;
}
return 0;
}
三 龙吸水(EASY)
1.题目
2.思路
待写