#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <utility>
using namespace std;
void update(int rank, int increment, vector<int>& binaryIndexTree)
{
while (rank < binaryIndexTree.size()) { // Increment the current rank and all higher ranks
binaryIndexTree[rank - 1] += increment;
rank += (rank & -rank);
}
}
int getValue(int rank, const vector<int>& binaryIndexTree)
{
auto result = 0;
while (rank > 0) { // Search the current rank and all lower ranks
result += binaryIndexTree[rank - 1]; // Sum any value found into result
rank -= (rank & -rank);
}
return result;
}
int main(void) {
vector<int> values{ 2, 3, 4, 3, 4, 1 };
// O(n*n) solution
vector<int> largerNumbers(values.size());
auto count = 0;
for (int i = values.size() - 1; i >= 0; --i){
for (int j = i + 1; j < values.size(); ++j){
if (values[i] < values[j]){
largerNumbers[i]++;
count += largerNumbers[j];
}
}
}
cout << "O(n*n): " << count << endl;
// O(nklogn) solution
int n = values.size(), k = 3; // k is the length of the subsequesnces
vector<vector<int>> cumBIT(k, vector<int>(n)); // 0 out cumBIT this is the binary tree
vector<int> temp(n); // Array for sorting
map<int, int> mapIndex; // This will translate from the value in index to the 1-based count of values less than it
partial_sort_copy(values.cbegin(), values.cend(), temp.begin(), temp.end());
for(auto i = 0; i < n; ++i){
mapIndex.insert(make_pair(temp[i], i + 1)); // insert will only allow each number to be added to the map the first time
}
vector<vector<int>> binaryIndexTree(k, vector<int>(n)); // A 2D binary index tree with depth k
auto result = 0;
for(auto it = values.cbegin(); it != values.cend(); ++it){
auto rank = mapIndex[*it];
auto value = 1; // Number of sequences to be added to this rank and all subsequent ranks
update(rank, value, binaryIndexTree[0]); // Populate the binary index tree for sub-sequences of length 1
for(auto i = 1; i < k; ++i){ // Itterate over all sub-sequence lengths 2 - k
value = getValue(rank - 1, binaryIndexTree[i - 1]); // Retrieve all possible shorter sub-sequences of lesser or equal rank
update(rank, value, binaryIndexTree[i]); // Update the binary index tree for sub sequences of this length
}
result += value; // Add the possible sub-sequences of length k for this rank
}
cout << "O(nklogn): " << result << endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8bWFwPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8dXRpbGl0eT4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgogICAgdm9pZCB1cGRhdGUoaW50IHJhbmssIGludCBpbmNyZW1lbnQsIHZlY3RvcjxpbnQ+JiBiaW5hcnlJbmRleFRyZWUpCgl7CgkgICAgd2hpbGUgKHJhbmsgPCBiaW5hcnlJbmRleFRyZWUuc2l6ZSgpKSB7IC8vIEluY3JlbWVudCB0aGUgY3VycmVudCByYW5rIGFuZCBhbGwgaGlnaGVyIHJhbmtzCgkgICAgICAgIGJpbmFyeUluZGV4VHJlZVtyYW5rIC0gMV0gKz0gaW5jcmVtZW50OwoJICAgICAgICByYW5rICs9IChyYW5rICYgLXJhbmspOwoJICAgIH0KCX0KCQoJaW50IGdldFZhbHVlKGludCByYW5rLCBjb25zdCB2ZWN0b3I8aW50PiYgYmluYXJ5SW5kZXhUcmVlKQoJewoJICAgIGF1dG8gcmVzdWx0ID0gMDsKCSAgICB3aGlsZSAocmFuayA+IDApIHsgLy8gU2VhcmNoIHRoZSBjdXJyZW50IHJhbmsgYW5kIGFsbCBsb3dlciByYW5rcwoJICAgICAgICByZXN1bHQgKz0gYmluYXJ5SW5kZXhUcmVlW3JhbmsgLSAxXTsgLy8gU3VtIGFueSB2YWx1ZSBmb3VuZCBpbnRvIHJlc3VsdAogICAgICAgICAgICByYW5rIC09IChyYW5rICYgLXJhbmspOwoJICAgIH0KCSAgICByZXR1cm4gcmVzdWx0OwoJfQoKaW50IG1haW4odm9pZCkgewogICB2ZWN0b3I8aW50PiB2YWx1ZXN7IDIsIDMsIDQsIDMsIDQsIDEgfTsKICAgCiAgIC8vIE8obipuKSBzb2x1dGlvbgogICB2ZWN0b3I8aW50PiBsYXJnZXJOdW1iZXJzKHZhbHVlcy5zaXplKCkpOwogICBhdXRvIGNvdW50ID0gMDsKCiAgICBmb3IgKGludCBpID0gdmFsdWVzLnNpemUoKSAtIDE7IGkgPj0gMDsgLS1pKXsKICAgICAgICBmb3IgKGludCBqID0gaSArIDE7IGogPCB2YWx1ZXMuc2l6ZSgpOyArK2opewogICAgICAgICAgICBpZiAodmFsdWVzW2ldIDwgdmFsdWVzW2pdKXsKICAgICAgICAgICAgICAgIGxhcmdlck51bWJlcnNbaV0rKzsKICAgICAgICAgICAgICAgIGNvdW50ICs9IGxhcmdlck51bWJlcnNbal07CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICBjb3V0IDw8ICJPKG4qbik6ICIgPDwgY291bnQgPDwgZW5kbDsKCiAgICAvLyBPKG5rbG9nbikgc29sdXRpb24KICAgIGludCBuID0gdmFsdWVzLnNpemUoKSwgayA9IDM7IC8vIGsgaXMgdGhlIGxlbmd0aCBvZiB0aGUgc3Vic2VxdWVzbmNlcwogICAgdmVjdG9yPHZlY3RvcjxpbnQ+PiBjdW1CSVQoaywgdmVjdG9yPGludD4obikpOyAvLyAwIG91dCBjdW1CSVQgdGhpcyBpcyB0aGUgYmluYXJ5IHRyZWUKICAgIHZlY3RvcjxpbnQ+IHRlbXAobik7IC8vIEFycmF5IGZvciBzb3J0aW5nCiAgICBtYXA8aW50LCBpbnQ+IG1hcEluZGV4OyAvLyBUaGlzIHdpbGwgdHJhbnNsYXRlIGZyb20gdGhlIHZhbHVlIGluIGluZGV4IHRvIHRoZSAxLWJhc2VkIGNvdW50IG9mIHZhbHVlcyBsZXNzIHRoYW4gaXQKICAgIAogICAgcGFydGlhbF9zb3J0X2NvcHkodmFsdWVzLmNiZWdpbigpLCB2YWx1ZXMuY2VuZCgpLCB0ZW1wLmJlZ2luKCksIHRlbXAuZW5kKCkpOwoKICAgIGZvcihhdXRvIGkgPSAwOyBpIDwgbjsgKytpKXsKICAgICAgICBtYXBJbmRleC5pbnNlcnQobWFrZV9wYWlyKHRlbXBbaV0sIGkgKyAxKSk7IC8vIGluc2VydCB3aWxsIG9ubHkgYWxsb3cgZWFjaCBudW1iZXIgdG8gYmUgYWRkZWQgdG8gdGhlIG1hcCB0aGUgZmlyc3QgdGltZQogICAgfQoKICAgIHZlY3Rvcjx2ZWN0b3I8aW50Pj4gYmluYXJ5SW5kZXhUcmVlKGssIHZlY3RvcjxpbnQ+KG4pKTsgLy8gQSAyRCBiaW5hcnkgaW5kZXggdHJlZSB3aXRoIGRlcHRoIGsKICAgIGF1dG8gcmVzdWx0ID0gMDsKCiAgICBmb3IoYXV0byBpdCA9IHZhbHVlcy5jYmVnaW4oKTsgaXQgIT0gdmFsdWVzLmNlbmQoKTsgKytpdCl7CiAgICAgICAgYXV0byByYW5rID0gbWFwSW5kZXhbKml0XTsKICAgICAgICBhdXRvIHZhbHVlID0gMTsgLy8gTnVtYmVyIG9mIHNlcXVlbmNlcyB0byBiZSBhZGRlZCB0byB0aGlzIHJhbmsgYW5kIGFsbCBzdWJzZXF1ZW50IHJhbmtzCiAgICAgICAgdXBkYXRlKHJhbmssIHZhbHVlLCBiaW5hcnlJbmRleFRyZWVbMF0pOyAvLyBQb3B1bGF0ZSB0aGUgYmluYXJ5IGluZGV4IHRyZWUgZm9yIHN1Yi1zZXF1ZW5jZXMgb2YgbGVuZ3RoIDEKCiAgICAgICAgZm9yKGF1dG8gaSA9IDE7IGkgPCBrOyArK2kpeyAvLyBJdHRlcmF0ZSBvdmVyIGFsbCBzdWItc2VxdWVuY2UgbGVuZ3RocyAyIC0gawogICAgICAgICAgICB2YWx1ZSA9IGdldFZhbHVlKHJhbmsgLSAxLCBiaW5hcnlJbmRleFRyZWVbaSAtIDFdKTsgLy8gUmV0cmlldmUgYWxsIHBvc3NpYmxlIHNob3J0ZXIgc3ViLXNlcXVlbmNlcyBvZiBsZXNzZXIgb3IgZXF1YWwgcmFuawogICAgICAgICAgICB1cGRhdGUocmFuaywgdmFsdWUsIGJpbmFyeUluZGV4VHJlZVtpXSk7IC8vIFVwZGF0ZSB0aGUgYmluYXJ5IGluZGV4IHRyZWUgZm9yIHN1YiBzZXF1ZW5jZXMgb2YgdGhpcyBsZW5ndGgKICAgICAgICB9CiAgICAgICAgcmVzdWx0ICs9IHZhbHVlOyAvLyBBZGQgdGhlIHBvc3NpYmxlIHN1Yi1zZXF1ZW5jZXMgb2YgbGVuZ3RoIGsgZm9yIHRoaXMgcmFuawogICAgfQoKICAgIGNvdXQgPDwgIk8obmtsb2duKTogIiA8PCByZXN1bHQgPDwgZW5kbDsKICAgIHJldHVybiAwOwp9