代码训练1
P1083 [NOIP 2012 提高组] 借教室
使用差分和二分查找优化算法
#include <stdio.h>
#include <string.h>
#define N 1000010
typedef long long LL;
int n, m;
int w[N]; // 每天的教室数量
int l[N], r[N], d[N]; // 订单的起始时间、结束时间和需要的教室数量
LL b[N]; // 差分数组,用于计算每天的需求
// 检查前 mid 个订单是否能满足
int check(int mid) {
memset(b, 0, sizeof(b)); // 初始化差分数组
for (int i = 1; i <= mid; i++) {
b[l[i]] += d[i]; // 订单i的需求
b[r[i] + 1] -= d[i]; // 结束时间后的需求减少
}
// 计算每日的教室需求并判断是否超过最大容量
for (int i = 1; i <= n; i++) {
b[i] += b[i - 1]; // 累加前一天的需求
if (b[i] > w[i]) return 0; // 如果需求超过最大容量,返回false
}
return 1; // 如果前 mid 个订单都能满足,返回true
}
int main() {
// 输入天数 n 和订单数量 m
scanf("%d %d", &n, &m);
// 输入每天的教室数量
for (int i = 1; i <= n; i++) {
scanf("%d", &w[i]);
}
// 输入每个订单的起始时间、结束时间和需要的教室数量
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &d[i], &l[i], &r[i]);
}
// 使用二分查找找最早无法满足的订单
int l = 0, r = m;
while (l < r) {
int mid = (l + r + 1) / 2; // 取中间值
if (check(mid)) {
l = mid; // 如果前 mid 个订单能满足,继续向右查找
} else {
r = mid - 1; // 否则向左查找
}
}
// 输出结果
if (r == m) {
printf("0\n"); // 如果所有订单都能满足,输出0
} else {
printf("-1\n%d\n", r + 1); // 否则输出最早无法满足的订单编号
}
return 0;
}