|
@@ -1,106 +1,85 @@
|
|
|
-const int MAXNUM = 1000;
|
|
|
-struct SegTreeNode
|
|
|
-{
|
|
|
- int val;
|
|
|
- int addMark;// label retardé
|
|
|
-} segTree[MAXNUM];
|
|
|
-
|
|
|
-/*
|
|
|
-arr: valeur des feuilles
|
|
|
-istart: indice début
|
|
|
-iend: indice end
|
|
|
-*/
|
|
|
-void build(int root, int arr[], int istart, int iend)
|
|
|
-{
|
|
|
- segTree[root].addMark = 0;
|
|
|
- if(istart == iend) // attend un feuille
|
|
|
- segTree[root].val = arr[istart];
|
|
|
- else
|
|
|
- {
|
|
|
- int mid = (istart + iend) / 2;
|
|
|
- build(root*2+1, arr, istart, mid); // créé l'arbre gauche
|
|
|
- build(root*2+2, arr, mid+1, iend); // créé l'arbre droit
|
|
|
- // calcul le min des deux
|
|
|
- segTree[root].val = min(segTree[root*2+1].val, segTree[root*2+2].val);
|
|
|
+// segment tree for minimum
|
|
|
+// root is in tree[1], children in tree[2i] and tree[2i+1]
|
|
|
+// all ranges in build/updates/queries are 0-based
|
|
|
+const int INFI=1000000000;
|
|
|
+struct Node {
|
|
|
+ int v; int up;
|
|
|
+ void update(int x) {
|
|
|
+ v += x;
|
|
|
+ up += x;
|
|
|
}
|
|
|
-}
|
|
|
-/*
|
|
|
-pushDown le label retardé
|
|
|
-*/
|
|
|
-void pushDown(int root)
|
|
|
-{
|
|
|
- if(segTree[root].addMark != 0)
|
|
|
- {
|
|
|
- segTree[root*2+1].addMark += segTree[root].addMark;
|
|
|
- segTree[root*2+2].addMark += segTree[root].addMark;
|
|
|
- segTree[root*2+1].val += segTree[root].addMark;
|
|
|
- segTree[root*2+2].val += segTree[root].addMark;
|
|
|
- segTree[root].addMark = 0;
|
|
|
+ Node() {
|
|
|
+ v = INFI;
|
|
|
+ up = 0;
|
|
|
}
|
|
|
+};
|
|
|
+Node *tree;
|
|
|
+int N;
|
|
|
+// read values[0..size-1]
|
|
|
+void build(int size, int values[]) {
|
|
|
+ N = 1 << ((int)log2(size-1)+1);
|
|
|
+ tree = new Node[2*N];
|
|
|
+ for(int i = 0; i < size; i++) // leaves
|
|
|
+ tree[N+i].v = values[i];
|
|
|
+ for(int i = N-1; i > 0; i--) // interns
|
|
|
+ tree[i].v = min(tree[2*i].v, tree[2*i+1].v);
|
|
|
+}
|
|
|
+void push(int v) {
|
|
|
+ if(2*v < 2*N) // left subtree
|
|
|
+ tree[2*v].update(tree[v].up);
|
|
|
+ if(2*v+1 < 2*N) // right subtree
|
|
|
+ tree[2*v+1].update(tree[v].up);
|
|
|
+ tree[v].up = 0;
|
|
|
}
|
|
|
-/*
|
|
|
-[nstart, nend]: intervale associé à root
|
|
|
-[qstart, qend]: intervale de la question
|
|
|
-*/
|
|
|
-int query(int root, int nstart, int nend, int qstart, int qend)
|
|
|
-{
|
|
|
- // pas d'intersection
|
|
|
- if(qstart > nend || qend < nstart)
|
|
|
- return INFINITE;
|
|
|
- // [nstart, nend] est inclu dans [qstart, qend]
|
|
|
- if(qstart <= nstart && qend >= nend)
|
|
|
- return segTree[root].val;
|
|
|
- pushDown(root);
|
|
|
- // min de la question sur les deux fils
|
|
|
- int mid = (nstart + nend) / 2;
|
|
|
- return min(query(root*2+1, nstart, mid, qstart, qend),
|
|
|
- query(root*2+2, mid + 1, nend, qstart, qend));
|
|
|
-
|
|
|
+// v: current vertex with corressponding range [left, right)
|
|
|
+// find mimimum in the rangeg [l, r)
|
|
|
+int query_aux(int v, int left, int right, int l, int r) {
|
|
|
+ push(v);
|
|
|
+ if(right <= l || r <= left) // outside
|
|
|
+ return INFI;
|
|
|
+ if(l <= left && right <= r) // inside
|
|
|
+ return tree[v].v;
|
|
|
+ int m = (left+right)/2;
|
|
|
+ int left_min = query_aux(2*v, left, m, l, r); // left subtree
|
|
|
+ int right_min = query_aux(2*v+1, m, right, l, r); // right
|
|
|
+ return min(left_min, right_min);
|
|
|
}
|
|
|
-
|
|
|
-/*
|
|
|
-change la valeur d'une feuille
|
|
|
-[nstart, nend]
|
|
|
-index: indice de la feuille dans arr
|
|
|
-addVal: différence à ajouter
|
|
|
-*/
|
|
|
-void updateOne(int root, int nstart, int nend, int index, int addVal)
|
|
|
-{
|
|
|
- if(nstart == nend)
|
|
|
- {
|
|
|
- if(index == nstart) // feuille cherchée
|
|
|
- segTree[root].val += addVal;
|
|
|
- return;
|
|
|
+int query(int l, int r) {
|
|
|
+ return query_aux(1, 0, N, l, r);
|
|
|
+}
|
|
|
+// update element at index i with value x
|
|
|
+void update(int i, int x) {
|
|
|
+ i+=N;
|
|
|
+ // push path from 1 to i
|
|
|
+ int po = N;
|
|
|
+ for(int v = 1; v < i;) {
|
|
|
+ push(v);
|
|
|
+ if(i & po)
|
|
|
+ v = 2*v + 1; // i on right
|
|
|
+ else
|
|
|
+ v = 2*v; // left
|
|
|
+ po /= 2;
|
|
|
}
|
|
|
- int mid = (nstart + nend) / 2;
|
|
|
- if(index <= mid) // à gauche
|
|
|
- updateOne(root*2+1, nstart, mid, index, addVal);
|
|
|
- else updateOne(root*2+2, mid+1, nend, index, addVal); // à droite
|
|
|
- // prend le minimum
|
|
|
- segTree[root].val = min(segTree[root*2+1].val, segTree[root*2+2].val);
|
|
|
+ tree[i].v = x; // update el
|
|
|
+ for(i /= 2; i > 0; i /= 2) // update all segments containing i
|
|
|
+ tree[i].v = min(tree[2*i].v, tree[2*i+1].v);
|
|
|
}
|
|
|
-
|
|
|
-/*
|
|
|
-Met à jour un intervale
|
|
|
-[nstart, nend]: intervale du noeud
|
|
|
-[ustart, uend]: intervale à mettre à jour
|
|
|
-addVal: différence à ajouter
|
|
|
-*/
|
|
|
-void update(int root, int nstart, int nend, int ustart, int uend, int addVal)
|
|
|
-{
|
|
|
- // pas d'intersection
|
|
|
- if(ustart > nend || uend < nstart)
|
|
|
+// v: the current vertex with corressponding range in [left, right)
|
|
|
+// add value x for element in range [l, r)
|
|
|
+void update_range_aux(int v, int left, int right, int l, int r, int x) {
|
|
|
+ push(v);
|
|
|
+ if(right <= l || r <= left)
|
|
|
return;
|
|
|
- // inclu
|
|
|
- if(ustart <= nstart && uend >= nend)
|
|
|
- {
|
|
|
- segTree[root].addMark += addVal;
|
|
|
- segTree[root].val += addVal;
|
|
|
+ if(l <= left && right <= r) {
|
|
|
+ tree[v].update(x);
|
|
|
return;
|
|
|
}
|
|
|
- pushDown(root);
|
|
|
- int mid = (nstart + nend) / 2;
|
|
|
- update(root*2+1, nstart, mid, ustart, uend, addVal);
|
|
|
- update(root*2+2, mid+1, nend, ustart, uend, addVal);
|
|
|
- segTree[root].val = min(segTree[root*2+1].val, segTree[root*2+2].val);
|
|
|
+ int m = (left+right)/2;
|
|
|
+ update_range_aux(2*v, left, m, l, r, x);
|
|
|
+ update_range_aux(2*v+1, m, right, l, r, x);
|
|
|
+ tree[v].v = min(tree[2*v].v, tree[2*v+1].v);
|
|
|
+}
|
|
|
+// update [l,r)
|
|
|
+void update_range(int l, int r, int x) {
|
|
|
+ update_range_aux(1, 0, N, l, r, x);
|
|
|
}
|