题目连接
题意:
处理 n 天的借教室信息, 第 i 天学校有 ri个教室可以租
m 份订单,每份订单有三个整数, d, s, t
【s, t】天租借教室 每天租 d个教室
借教室原则先到先得,如果遇到一份订单无法满足,停止分配
通知申请人修改订单,(无法满足:从s, 到 t 天中至少有一天剩余的教室不足d个)
求是否有订单无法完全满足, 如果有通知哪个申请人
思路:
数据范围 n ,m 1e6, (0<= r, d <= 1e9),(1 <= s, t <= n)
1)区间更新,每次更新都要+ 判断,
2)判断每个点是否有负值,如果有负值,输出需要修改订单的申请人编号
3)用线段树
4) 差分数组
关于二分:
关于答案二分一般来说,二分是个很有用的优化途径,
因为这样会直接导致减半运算,而对于能否二分,
有一个界定标准:
状态的决策过程或者序列是否满足单调性或者可以局部舍弃性。
而在这个题里,因为如果前一份订单都不满足,
那么之后的所有订单都不用继续考虑;
而如果后一份订单都满足,那么之前的所有订单一定都可以满足,
符合局部舍弃性,所以可以二分订单数量。
AC:
/*
题意:
处理 n 天的借教室信息, 第 i 天学校有 ri个教室可以租
m 份订单,每份订单有三个整数, d, s, t
【s, t】天租借教室 每天租 d个教室
借教室原则先到先得,如果遇到一份订单无法满足,停止分配
通知申请人修改订单,(无法满足:从s, 到 t 天中至少有一天剩余的教室不足d个)
求是否有订单无法完全满足, 如果有通知哪个申请人
思路:
数据范围 n ,m 1e6, (0<= r, d <= 1e9),(1 <= s, t <= n)
1)区间更新,每次更新都要+ 判断,
2)判断每个点是否有负值,如果有负值,输出需要修改订单的申请人编号
3)用线段树
4) 差分数组
关于二分:
关于答案二分一般来说,二分是个很有用的优化途径,
因为这样会直接导致减半运算,而对于能否二分,
有一个界定标准:
状态的决策过程或者序列是否满足单调性或者可以局部舍弃性。
而在这个题里,因为如果前一份订单都不满足,
那么之后的所有订单都不用继续考虑;
而如果后一份订单都满足,那么之前的所有订单一定都可以满足,
符合局部舍弃性,所以可以二分订单数量。
*/
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stdio.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6;
int N, M;
int Rest[maxn + 10];
int F[maxn + 10];
//int Need[maxn + 10];
struct node{
int L, R;
int d;
}Inter[maxn + 10];
bool Solve(int x) {
bool flag = 1;
memset(F, 0, sizeof(F));
for(int i = 1; i <= x; ++i) {
F[Inter[i].L] += Inter[i].d;
F[Inter[i].R + 1] -= Inter[i].d;
}
int Temp = 0;
for(int i = 1; i <= N; ++i) {
Temp += F[i];
if(Temp > Rest[i]){
flag = 0;
break;
}
}
return flag;
}
int main() {
//freopen("in.txt", "r", stdin);
scanf("%d%d", &N, &M);
for(int i = 1; i <= N; ++i) {
scanf("%d", &Rest[i]);
F[i] = Rest[i] - F[i-1];
}
int d, s, t;
for(int i = 1; i <= M; ++i) {
scanf("%d%d%d", &Inter[i].d, &Inter[i].L, &Inter[i].R);
}
if(Solve(M)) {
printf("0");
return 0;
}
int left = 1, right = M;
while(left < right) {
int mid = (left + right) / 2;
if (Solve(mid))
left = mid + 1;
else
right = mid;
}
printf("-1\n");
printf("%d", left);
return 0;
}