[NOIP2012]借教室
二分答案,用差分+前缀和check
code:
#include<bits/stdc++.h>
using namespace std;
const int N = 1100000;
int n,m;
int r[N],d[N],s[N],t[N],b[N];
//检查函数
bool check(int k){
//复制数组(r为前缀和形式)
for (int i = 1;i<= n; i++) b[i] = r[i];
//处理(两点)
for (int i = 1;i<= k; i++){
b[s[i]] -= d[i];
b[t[i] + 1] += d[i];
}
//判断
int aa=0;
for (int i = 1; i <= n; i++){
aa+=b[i];
if(aa<0) return true;
}
return false;
}
int main(){
freopen("cla.in","r",stdin);
//读入
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]);
//用前缀和(但是是减法)重新处理r
for (int i=n; i>0; i--) r[i]-=r[i-1];
//二分
int l=1, r1=m;
while (l<r1){
int mid=(l+r1)/2;
if(check(mid)) r1=mid;
else l=mid+1;
}
//判断输出
if (check(r1)) printf("-1\n%d\n", r1);
else printf("0");
return 0;
}
这篇博客介绍了如何使用二分搜索和差分前缀和技巧解决NOIP2012竞赛中的借教室问题。通过重构数组并进行快速检查,博主展示了如何在O(n log m)时间内找到满足条件的最小操作次数。关键步骤包括复制数组、处理两点操作以及利用前缀和判断数组变化。

被折叠的 条评论
为什么被折叠?



