mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
Updated
This commit is contained in:
parent
37d2a06719
commit
558b74f1dd
@ -1,7 +1,6 @@
|
|||||||
#include<iostream>
|
#include<iostream>
|
||||||
#include<vector>
|
#include<vector>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
// query -> range sum
|
// query -> range sum
|
||||||
class perSegTree {
|
class perSegTree {
|
||||||
@ -10,17 +9,17 @@ private:
|
|||||||
public:
|
public:
|
||||||
Node *left;
|
Node *left;
|
||||||
Node *right;
|
Node *right;
|
||||||
long long val, prop;
|
int64_t val, prop;
|
||||||
int version;
|
int version;
|
||||||
|
|
||||||
Node() {
|
Node() {
|
||||||
left = right = NULL;
|
left = right = nullptr;
|
||||||
val = prop = version = 0;
|
val = prop = version = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int n; // number of elements in the segment tree
|
int n; // number of elements in the segment tree
|
||||||
vector<Node *> ptrs; // ptrs[i] holds a root pointer to the segment tree after the ith update
|
std::vector<Node *> ptrs; // ptrs[i] holds a root pointer to the segment tree after the ith update
|
||||||
Node *newKid(Node *curr) {
|
Node *newKid(Node *curr) {
|
||||||
Node *newNode = new Node();
|
Node *newNode = new Node();
|
||||||
*newNode = *curr;
|
*newNode = *curr;
|
||||||
@ -28,8 +27,9 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void lazy(int i, int j, Node *curr) {
|
void lazy(int i, int j, Node *curr) {
|
||||||
if (!curr->prop)
|
if (!curr->prop) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
curr->val += (j - i + 1) * curr->prop;
|
curr->val += (j - i + 1) * curr->prop;
|
||||||
if (i != j) {
|
if (i != j) {
|
||||||
curr->left = newKid(curr->left);
|
curr->left = newKid(curr->left);
|
||||||
@ -41,11 +41,11 @@ private:
|
|||||||
curr->prop = 0;
|
curr->prop = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void construct(int i, int j, vector<int> &vec, Node *&curr) {
|
void construct(int i, int j, std::vector<int> &vec, Node *&curr) {
|
||||||
curr = new Node();
|
curr = new Node();
|
||||||
if (i == j)
|
if (i == j) {
|
||||||
curr->val = vec[i];
|
curr->val = vec[i];
|
||||||
else {
|
} else {
|
||||||
int mid = i + (j - i) / 2;
|
int mid = i + (j - i) / 2;
|
||||||
construct(i, mid, vec, curr->left);
|
construct(i, mid, vec, curr->left);
|
||||||
construct(mid + 1, j, vec, curr->right);
|
construct(mid + 1, j, vec, curr->right);
|
||||||
@ -62,8 +62,9 @@ private:
|
|||||||
lazy(i, j, newNode);
|
lazy(i, j, newNode);
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
if (i > r || j < l)
|
if (i > r || j < l) {
|
||||||
return curr;
|
return curr;
|
||||||
|
}
|
||||||
Node *newNode = new Node();
|
Node *newNode = new Node();
|
||||||
int mid = i + (j - i) / 2;
|
int mid = i + (j - i) / 2;
|
||||||
newNode->left = update(i, mid, l, r, value, curr->left);
|
newNode->left = update(i, mid, l, r, value, curr->left);
|
||||||
@ -73,76 +74,68 @@ private:
|
|||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
long long query(int i, int j, int l, int r, Node *curr) {
|
int64_t query(int i, int j, int l, int r, Node *curr) {
|
||||||
lazy(i, j, curr);
|
lazy(i, j, curr);
|
||||||
if (j < l || r < i)
|
if (j < l || r < i) {
|
||||||
return 0;
|
return 0;
|
||||||
if (i >= l && j <= r)
|
}
|
||||||
|
if (i >= l && j <= r) {
|
||||||
return curr->val;
|
return curr->val;
|
||||||
|
}
|
||||||
int mid = i + (j - i) / 2;
|
int mid = i + (j - i) / 2;
|
||||||
return query(i, mid, l, r, curr->left) + query(mid + 1, j, l, r, curr->right);
|
return query(i, mid, l, r, curr->left) + query(mid + 1, j, l, r, curr->right);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear(Node *&curr, int version) {
|
void clear(Node *&curr, int version) {
|
||||||
if (!curr || curr->version != version)
|
if (!curr || curr->version != version) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
clear(curr->left, version);
|
clear(curr->left, version);
|
||||||
clear(curr->right, version);
|
clear(curr->right, version);
|
||||||
delete curr;
|
delete curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValidRange(int l, int r) {
|
public:
|
||||||
return l <= r && l >= 0 && l < n && r >= 0 && r < n;
|
perSegTree() {
|
||||||
|
n = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
void construct(std::vector<int> &vec) // the segment tree will be built from the values in "vec", "vec" is 0 indexed
|
||||||
void construct(vector<int> &vec) // the segment tree will be built from the values in "vec", "vec" is 0 indexed
|
|
||||||
{
|
{
|
||||||
if (vec.empty())
|
if (vec.empty()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
n = vec.size();
|
n = vec.size();
|
||||||
Node *root;
|
Node *root = nullptr;
|
||||||
construct(0, n - 1, vec, root);
|
construct(0, n - 1, vec, root);
|
||||||
ptrs.push_back(root);
|
ptrs.push_back(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(int l, int r, int value) // all elements from index "l" to index "r" would by updated by "value", "l" and "r" are 0 indexed
|
void update(int l, int r,
|
||||||
|
int value) // all elements from index "l" to index "r" would by updated by "value", "l" and "r" are 0 indexed
|
||||||
{
|
{
|
||||||
try {
|
ptrs.push_back(update(0, n - 1, l, r, value,
|
||||||
if (!ptrs.size()) // if function "construct" is not called yet
|
ptrs[ptrs.size() - 1])); // saving the root pointer to the new segment tree
|
||||||
throw "Original segment tree does'nt exist";
|
|
||||||
if (!isValidRange(l, r)) // checking if the range is valid
|
|
||||||
throw "Invalid range";
|
|
||||||
ptrs.push_back(update(0, n - 1, l, r, value,ptrs[ptrs.size() - 1])); // saving the root pointer to the new segment tree
|
|
||||||
}
|
|
||||||
catch (const char *error) {
|
|
||||||
cout << error << '\n';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long long query(int l, int r, int version) // querying the range from "l" to "r" in a segment tree after "version" updates, "l" and "r" are 0 indexed
|
int64_t query(int l, int r,
|
||||||
|
int version) // querying the range from "l" to "r" in a segment tree after "version" updates, "l" and "r" are 0 indexed
|
||||||
{
|
{
|
||||||
try {
|
|
||||||
if (!isValidRange(l, r)) // checking if the range is valid
|
|
||||||
throw "Invalid range";
|
|
||||||
if (!(version >= 0 && version < ptrs.size())) // checking if "version" is not a valid version of any segment tree after updates so far
|
|
||||||
throw "Invalid version";
|
|
||||||
return query(0, n - 1, l, r, ptrs[version]);
|
return query(0, n - 1, l, r, ptrs[version]);
|
||||||
}
|
}
|
||||||
catch (const char *error) {
|
|
||||||
cout << error << '\n';
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
for (int i = ptrs.size() - 1; i >= 0; --i)
|
for (int i = (int) ptrs.size() - 1; i >= 0; --i) {
|
||||||
clear(ptrs[i],i); // every segment tree clears its nodes (nodes that were created when this segment tree was created)
|
clear(ptrs[i],
|
||||||
while (!ptrs.empty())
|
i); // every segment tree clears its nodes (nodes that were created when this segment tree was created)
|
||||||
|
}
|
||||||
|
while (!ptrs.empty()) {
|
||||||
ptrs.pop_back();
|
ptrs.pop_back();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int size() // returns the number of segment trees (versions) , the number of updates done so far = returned value - 1 ,because one of the trees is the original segment tree
|
int
|
||||||
|
size() // returns the number of segment trees (versions) , the number of updates done so far = returned value - 1 ,because one of the trees is the original segment tree
|
||||||
{
|
{
|
||||||
return ptrs.size();
|
return ptrs.size();
|
||||||
}
|
}
|
||||||
@ -150,37 +143,40 @@ public:
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|
||||||
vector<int> arr = {-5, 2, 3, 11, -2, 7, 0, 1};
|
std::vector<int> arr = {-5, 2, 3, 11, -2, 7, 0, 1};
|
||||||
perSegTree tree;
|
perSegTree tree;
|
||||||
cout << "Elements before any updates are {";
|
std::cout << "Elements before any updates are {";
|
||||||
for (int i = 0; i < arr.size(); ++i) {
|
for (int i = 0; i < arr.size(); ++i) {
|
||||||
cout << arr[i];
|
std::cout << arr[i];
|
||||||
if (i != arr.size() - 1)
|
if (i != arr.size() - 1) {
|
||||||
cout << ",";
|
std::cout << ",";
|
||||||
}
|
}
|
||||||
cout << "}\n";
|
}
|
||||||
|
std::cout << "}\n";
|
||||||
tree.construct(arr); // constructing the original segment tree (version = 0)
|
tree.construct(arr); // constructing the original segment tree (version = 0)
|
||||||
cout << "Querying range sum on version 0 from index 2 to 4 = 3+11-2 = " << tree.query(2, 4, 0) << '\n';
|
std::cout << "Querying range sum on version 0 from index 2 to 4 = 3+11-2 = " << tree.query(2, 4, 0) << '\n';
|
||||||
cout << "Subtract 7 from all elements from index 1 to index 5 inclusive\n";
|
std::cout << "Subtract 7 from all elements from index 1 to index 5 inclusive\n";
|
||||||
tree.update(1, 5, -7); // subtracting 7 from index 1 to index 5
|
tree.update(1, 5, -7); // subtracting 7 from index 1 to index 5
|
||||||
cout << "Elements of the segment tree whose version = 1 (after 1 update) are {";
|
std::cout << "Elements of the segment tree whose version = 1 (after 1 update) are {";
|
||||||
for (int i = 0; i < arr.size(); ++i) {
|
for (int i = 0; i < arr.size(); ++i) {
|
||||||
cout << tree.query(i, i, 1);
|
std::cout << tree.query(i, i, 1);
|
||||||
if (i != arr.size() - 1)
|
if (i != arr.size() - 1) {
|
||||||
cout << ",";
|
std::cout << ",";
|
||||||
}
|
}
|
||||||
cout << "}\n";
|
}
|
||||||
cout << "Add 10 to all elements from index 0 to index 7 inclusive\n";
|
std::cout << "}\n";
|
||||||
|
std::cout << "Add 10 to all elements from index 0 to index 7 inclusive\n";
|
||||||
tree.update(0, 7, 10); // adding 10 to all elements
|
tree.update(0, 7, 10); // adding 10 to all elements
|
||||||
cout << "Elements of the segment tree whose version = 2 (after 2 updates) are {";
|
std::cout << "Elements of the segment tree whose version = 2 (after 2 updates) are {";
|
||||||
for (int i = 0; i < arr.size(); ++i) {
|
for (int i = 0; i < arr.size(); ++i) {
|
||||||
cout << tree.query(i, i, 2);
|
std::cout << tree.query(i, i, 2);
|
||||||
if (i != arr.size() - 1)
|
if (i != arr.size() - 1) {
|
||||||
cout << ",";
|
std::cout << ",";
|
||||||
}
|
}
|
||||||
cout << "}\n";
|
}
|
||||||
cout << "Number of segment trees (versions) now = " << tree.size() << '\n';
|
std::cout << "}\n";
|
||||||
cout << "Querying range sum on version 0 from index 3 to 5 = 11-2+7 = " << tree.query(3, 5, 0) << '\n';
|
std::cout << "Number of segment trees (versions) now = " << tree.size() << '\n';
|
||||||
cout << "Querying range sum on version 1 from index 3 to 5 = 4-9+0 = " << tree.query(3, 5, 1) << '\n';
|
std::cout << "Querying range sum on version 0 from index 3 to 5 = 11-2+7 = " << tree.query(3, 5, 0) << '\n';
|
||||||
|
std::cout << "Querying range sum on version 1 from index 3 to 5 = 4-9+0 = " << tree.query(3, 5, 1) << '\n';
|
||||||
tree.clear();
|
tree.clear();
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user