刚看到题的时候秒打了个差分上去,然后发现要输出第一个不满足条件的合同。。。当时以为这是差分的子任务,就觉得这个东西随便找找就好了吧,然后就怎么也找不出来Orz
事实证明,差分确实难打方案。。。
后来才知道找订单才是主要的。。。需要二分答案来着。。。因为题目强制给你单调性了(完成订单的顺序必须满足输入顺序)所以我们可以二分一个最开始不能完成的订单,然后检查这个订单是不是真的不满足就可以了。若这个订单满足,就往后找,反之往左找。
判断就是差分了,每次一个订单需要覆盖区间的时候,把区间的左端点加d[i],右端点+1的位置减d[i],i指的是订单,范围是1到二分的那个答案。最后对某天求前缀和,即可求出某一天需要多少教室
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 1000000 + 10;
int n,m,seq[MAXN],d[MAXN],r[MAXN],s[MAXN],t[MAXN],ans,temp;
bool jud(int mid) {
bool flg = false;
memset(seq,0,sizeof(seq));
temp = 0;
for(int i=1; i<=mid; i++) {
seq[s[i]]+=d[i];
seq[t[i]+1]-=d[i];
}
for(int i=1; i<=n; i++) {
temp += seq[i];
if(temp > r[i]) {
flg = true;
break;
}
}
return flg;
}
int main() {
scanf("%d %d",&n,&m);
for(int i=1; i<=n; i++)
scanf("%d", &r[i]);
for(int i=1; i<=m; i++)
scanf("%d %d %d",&d[i],&s[i],&t[i]);
int l = 1, rr = m;
while(l <= rr) {
int mid = l+rr>>1;
if(jud(mid)) {
ans = mid;
rr = mid - 1;
}
else
l = mid + 1;
}
if(!ans) printf("0");
else {
printf("-1\n");
printf("%d",ans);
}
return 0;
}