제출 #498661

#제출 시각아이디문제언어결과실행 시간메모리
498661model_codeWeirdtree (RMI21_weirdtree)C++17
100 / 100
881 ms29632 KiB
// weirdtree_100_segtreebeats_ruxandra.cpp #include <bits/stdc++.h> #include "weirdtree.h" #define DIMN 300010 using namespace std; struct segm_tree{ long long sum; int maxi1, cntmaxi1, maxi2, lazy; /// lazy este cea mai mare valoare care poate sa apara ever in subarb } aint[4*DIMN]; int v[DIMN], n; segm_tree combine (segm_tree a , segm_tree b){ segm_tree c; c.sum = a.sum + b.sum; if (a.maxi1 > b.maxi1){ c.maxi1 = a.maxi1; c.cntmaxi1 = a.cntmaxi1; c.maxi2 = max(a.maxi2 , b.maxi1); } else if (a.maxi1 < b.maxi1){ c.maxi1 = b.maxi1; c.cntmaxi1 = b.cntmaxi1; c.maxi2 = max(b.maxi2 , a.maxi1); } else { /// egale c.maxi1 = a.maxi1; c.cntmaxi1 = a.cntmaxi1 + b.cntmaxi1; c.maxi2 = max(b.maxi2 , a.maxi2); } c.lazy = max(a.lazy, b.lazy); return c; } void lazy_update (int nod , int st , int dr){ /// the maximum value in the interval st , dr must be aint[nod].lazy if (st == dr) return; if (aint[nod].lazy < aint[2 * nod].maxi1){ aint[2 * nod].sum = aint[2 * nod].sum - 1LL * aint[2 * nod].maxi1 * aint[2 * nod].cntmaxi1 + 1LL * aint[nod].lazy * aint[2 * nod].cntmaxi1; aint[2 * nod].maxi1 = aint[nod].lazy; aint[2 * nod].lazy = min(aint[2 * nod].lazy , aint[nod].lazy); } if (aint[nod].lazy < aint[2 * nod + 1].maxi1){ aint[2 * nod + 1].sum = aint[2 * nod + 1].sum - 1LL * aint[2 * nod + 1].maxi1 * aint[2 * nod + 1].cntmaxi1 + 1LL * aint[nod].lazy * aint[2 * nod + 1].cntmaxi1; aint[2 * nod + 1].maxi1 = aint[nod].lazy; aint[2 * nod + 1].lazy = min(aint[2 * nod + 1].lazy , aint[nod].lazy); } } void build (int nod, int st , int dr){ int mid = (st + dr)/2; if (st == dr){ aint[nod].sum = v[st]; aint[nod].maxi1 = v[st]; aint[nod].cntmaxi1 = 1; aint[nod].maxi2 = 0; aint[nod].lazy = v[st]; return; } build (2 * nod , st , mid); build (2 * nod + 1 , mid + 1 , dr); aint[nod] = combine(aint[2 * nod] , aint[2 * nod + 1]); } segm_tree query (int nod , int st , int dr, int l , int r){ segm_tree sol = {0, 0 , 0 , 0, 0}; int mid = (st + dr)/2; lazy_update (nod , st , dr); if (l <= st && dr <= r){ sol = aint[nod]; return sol; } if (l <= mid){ sol = combine(sol , query(2 * nod , st , mid , l , r)); } if (mid + 1 <= r){ sol = combine(sol , query(2 * nod + 1 , mid + 1 , dr , l , r)); } lazy_update (2 * nod , st , mid); lazy_update (2 * nod + 1 , mid + 1 , dr); aint[nod] = combine(aint[2 * nod] , aint[2 * nod + 1]); return sol; } void update (int nod , int st , int dr , int l , int r , int &capacity, int maxi){ int mid = (st + dr)/2; lazy_update (nod , st , dr); if (st > r || dr < l || aint[nod].maxi1 <= maxi - (capacity > 0)){ return; /// nothing to change here } if (l <= st && dr <= r && aint[nod].maxi1 > maxi - (capacity > 0) && (aint[nod].maxi2 < maxi - (capacity > 0) || (aint[nod].cntmaxi1 == dr - st + 1)) && (!capacity || capacity >= aint[nod].cntmaxi1)){ if (!capacity){ aint[nod].sum = aint[nod].sum - 1LL * aint[nod].maxi1 * aint[nod].cntmaxi1 + 1LL * maxi * aint[nod].cntmaxi1; aint[nod].lazy = maxi; aint[nod].maxi1 = maxi; } else { /// the whole interval is 1 less aint[nod].sum = aint[nod].sum - 1LL * aint[nod].maxi1 * aint[nod].cntmaxi1 + 1LL * (maxi - 1) * aint[nod].cntmaxi1; aint[nod].lazy = maxi - 1; aint[nod].maxi1 = maxi - 1; capacity -= aint[nod].cntmaxi1; } lazy_update (nod,st,dr); return; } if (l <= mid) update (2 * nod , st , mid , l , r , capacity , maxi); if (mid + 1 <= r) update (2 * nod + 1 , mid + 1 , dr , l , r , capacity , maxi); lazy_update (2 * nod , st , mid); lazy_update (2 * nod + 1 , mid + 1 , dr); aint[nod] = combine(aint[2 * nod] , aint[2 * nod + 1]); } void update_value (int nod , int st , int dr , int pos , int val){ int mid = (st + dr)/2; lazy_update (nod , st , dr); if (st == dr){ aint[nod].sum = val; aint[nod].maxi1 = val; aint[nod].cntmaxi1 = 1; aint[nod].maxi2 = 0; aint[nod].lazy = val; return; } if (pos <= mid) update_value (2 * nod , st , mid , pos , val); else update_value (2 * nod + 1 , mid + 1 , dr , pos , val); lazy_update (2 * nod , st , mid); lazy_update (2 * nod + 1 , mid + 1 , dr); aint[nod] = combine(aint[2 * nod] , aint[2 * nod + 1]); } void initialise (int N , int q , int h[]){ int i; n = N; for (i = 1 ; i <= n ; i++){ v[i] = h[i]; } build (1 , 1 , n); } void cut (int l, int r, int k){ segm_tree ans; long long cuts; int capacity; while (k){ ans = query (1 , 1 , n , l , r); if (ans.maxi1 == 0){ /// not much you can do return; } cuts = 1LL * (ans.maxi1 - ans.maxi2) * ans.cntmaxi1; if (cuts <= k){ /// all values equal to maxi1 become equal to maxi2 in [l , r] k -= cuts; capacity = 0; update (1 , 1 , n , l , r , capacity, ans.maxi2); } else { /// too many values bigger than maxi2, do stuff int valueToReach = ans.maxi1 - k / ans.cntmaxi1; capacity = k % ans.cntmaxi1; update (1 , 1 , n , l , r , capacity , valueToReach); k = 0; } } } void magic (int i, int k){ update_value (1 , 1 , n , i , k); } long long inspect (int l, int r){ return query(1 , 1 , n , l , r).sum; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...