1. 程式人生 > >NOIP2012 借教室 (線段樹)

NOIP2012 借教室 (線段樹)

Solution

考慮用線段樹維護,每借一段時間的教師便線上段樹中減去對應的值,不理解為什麼網上這麼多二分的。。

Code

//Author: Hany01
//Date: Nov 5th. 2017
#include<bits/stdc++.h>
#define For(i , j , k) for (int i = (j) , i##_end_ = (k) ; i <= i##_end_ ; ++ i)
#define Fordown(i , j , k) for (int i = (j) , i##_end_ = (k) ; i >= i##_end_ ; -- i)
#define Set(a , b) memset(a , b , sizeof(a)) #define lc (t << 1) #define rc (lc | 1) #define mid ((l + r) >> 1) #define pb push_back #define INF (0x3f3f3f3f) #define Mod (1000000007) using namespace std; typedef long long LL; template <typename T> inline bool chkmax(T &a , T b) { return
a < b ? (a = b , 1) : 0; } template <typename T> inline bool chkmin(T &a , T b) { return b < a ? (a = b , 1) : 0; } int _ , __; char c_; inline int read() { for (_ = 0 , __ = 1 , c_ = getchar() ; !isdigit(c_) ; c_ = getchar()) if (c_ == '-') __ = -1; for ( ; isdigit(c_) ; c_ = getchar()) _ = (_ << 1
) + (_ << 3) + (c_ ^ 48); return _ * __; } inline void File() { #ifdef hany01 freopen("classroom.in" , "r" , stdin); freopen("classroom.out" , "w" , stdout); #endif } const int maxn = 1000010; int tr[maxn << 2], addv[maxn << 2], n, m, dt, x, y; inline void maintain(int t) { tr[t] = min(tr[lc], tr[rc]); } inline void pushdown(int t) { if (!addv[t]) return ; tr[lc] += addv[t]; tr[rc] += addv[t]; addv[lc] += addv[t]; addv[rc] += addv[t]; addv[t] = 0; } void build(int t, int l, int r) { if (l == r) { tr[t] = read(); return; } build(lc, l, mid); build(rc, mid + 1, r); maintain(t); } void update(int t, int l, int r) { if (x <= l && r <= y) { tr[t] += dt; addv[t] += dt; return; } pushdown(t); if (x <= mid) update(lc, l, mid); if (y > mid) update(rc, mid + 1, r); maintain(t); } int main() { File(); n = read(); m = read(); build(1, 1, n); For(Case, 1, m) { dt = -read(); x = read(); y = read(); update(1, 1, n); if (tr[1] < 0) { printf("-1\n%d\n", Case); return 0; } } puts("0"); return 0; } //靜夜四無鄰,荒居舊業貧。 //雨中黃葉樹,燈下白頭人。 //以我獨沉久,愧君相見頻。 //平生自有分,況是霍家親。 //--司空曙《喜見外弟盧綸見宿》