luogu P1083 借教室
二次联通门 : luogu P1083 借教室
/* luogu P1083 借教室 二分 + 前缀和 + 贪心 其实一看这个题我是想用线段树去做的.... 根本看不出从哪里要二分.. 思路: 二分一下订单的编号 检查答案是否可行, 可行就向后找 , 否则就向前找.. 前缀和是第 i 天需要的教室数 具体检查过程 做一下前缀和 比如 l~r 天要x个教室 那么 sum[l] += x sum[r + 1] -= x 这样的话就处理出了第i天要借的教室数 最后加起来看看是否超过原有的教室即可 */ #include <iostream> #include <cstring> #include <cstdio> #define Max 1000209 using namespace std; void read (int &now) { now = 0; char word = getchar (); while (word < '0' || word > '9') word = getchar (); while (word >= '0' && word <= '9') { now = now * 10 + word - '0'; word = getchar (); } } int N; int M; int sum[Max]; int number[Max]; int Answer; struct Ruri { int number; int start; int end; }res[Max]; bool Check (int day) { memset (sum, 0, sizeof (sum)); int now = 0; for (int i = 1; i <= day; i++) { sum[res[i].start] += res[i].number; sum[res[i].end + 1] -= res[i].number; } for (int i = 1; i <= N; i++) { now += sum[i]; if (now > number[i]) return false; } return true; } int main (int argc, char *argv[]) { read (N); read (M); for (int i = 1; i <= N; i++) read (number[i]); for (int i = 1; i <= M; i++) { read (res[i].number); read (res[i].start); read (res[i].end); } int l = 1; int r = M; int Mid; while (l <= r) { Mid = (l + r) >> 1; if (Check (Mid)) l = Mid + 1; else { Answer = Mid; r = Mid - 1; } } if (!Answer) putchar ('0'); else printf ("-1\n%d", Answer); return 0; }
myj 吊打我Orz,xxy 捆起来打我Orz,myl 文化课上天Orz, lrh 姿势水平敲高Orz, hkd 特别胖Orz%%%,cys 智商感人Orz,syl zz专业Orz,我没有学上, 我们未来一片光明