pb_ds库实现支持多个相同的值的名次树

阅读量: searchstar 2019-06-30 19:37:05
Categories: Tags:

参考的大佬的博客的链接:
https://blog.csdn.net/onepointo/article/details/75083305

//luogu_3369
#include <stdio.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long LL;

tree<LL, null_type, less<LL>, rb_tree_tag, tree_order_statistics_node_update> t;
map<int, int> ma;
void Insert(int v) {
    t.insert(((LL)v << 32) + ++ma[v]);
}

void Delete(int v) {
    auto it = ma.find(v);
    t.erase(((LL)v << 32) + it->second);
    --it->second;
    if (0 == it->second) {
        ma.erase(it);
    }
}

int RankOf(int v) {
    return t.order_of_key((LL)v << 32) + 1;
}

int FindByRank(int r) {
    return *t.find_by_order(r-1) >> 32;
}

int FindPre(int v) {
    auto it = ma.lower_bound(v);
    --it;
    return it->first;
}

int FindNext(int v) {
    return ma.upper_bound(v)->first;
}

int main() {
    int n;
    scanf("%d", &n);
    while (n--) {
        int op, x;
        scanf("%d%d", &op, &x);
        switch (op) {
        case 1:
            Insert(x);
            break;
        case 2:
            Delete(x);
            break;
        case 3:
            printf("%d\n", RankOf(x));
            break;
        case 4:
            printf("%d\n", FindByRank(x));
            break;
        case 5:
            printf("%d\n", FindPre(x));
            break;
        case 6:
            printf("%d\n", FindNext(x));
            break;
        }
    }
    return 0;
}

注意如果less<LL>不小心写成了less<int>,编译器不会报错,但是答案是错的。

另一种不用map来求前驱和后继的比较和谐的方法:

//luogu_3369
#include <stdio.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long LL;

tree<LL, null_type, less<LL>, rb_tree_tag, tree_order_statistics_node_update> t;
map<int, int> ma;
void Insert(int v) {
    t.insert(((LL)v << 32) + ++ma[v]);
}

void Delete(int v) {
    t.erase(((LL)v << 32) + ma[v]--);
}

int RankOf(int v) {
    return t.order_of_key((LL)v << 32) + 1;
}

int FindByRank(int r) {
    return *t.find_by_order(r-1) >> 32;
}

int FindPre(int v) {
    auto it = t.lower_bound((LL)v << 32);
    --it;
    return *it >> 32;
}

int FindNext(int v) {
    return *t.lower_bound((LL)(v+1) << 32) >> 32;
}

int main() {
    int n;
    scanf("%d", &n);
    while (n--) {
        int op, x;
        scanf("%d%d", &op, &x);
        switch (op) {
        case 1:
            Insert(x);
            break;
        case 2:
            Delete(x);
            break;
        case 3:
            printf("%d\n", RankOf(x));
            break;
        case 4:
            printf("%d\n", FindByRank(x));
            break;
        case 5:
            printf("%d\n", FindPre(x));
            break;
        case 6:
            printf("%d\n", FindNext(x));
            break;
        }
    }
    return 0;
}

封装版:

//luogu_3369
#include <stdio.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

template<typename T, typename less>
struct Cmp_MultiSet {
	bool operator () (const pair<T, size_t>& x, const pair<T, size_t>& y) const {
		return less()(x.first, y.first) ? true : (less()(y.first, x.first) ? false : less()(x.second, y.second));
	}
};

template<typename T, typename less>
struct MultiSet {
	tree<pair<T, size_t>, null_type, Cmp_MultiSet<T, less>, rb_tree_tag, tree_order_statistics_node_update> t;
	map<T, size_t> ma;
	void Insert(T v) {
		t.insert(make_pair(v, ++ma[v]));
	}
	void Delete(T v) {
		t.erase(make_pair(v, ma[v]--));
	}
	size_t RankOf(T v) {
		return t.order_of_key(make_pair(v, 0)) + 1;
	}
	T FindByRank(size_t r) {
		return t.find_by_order(r-1)->first;
	}
	T FindPre(T v) {
		auto it = t.lower_bound(make_pair(v, 0));
		return (--it)->first;
	}
	T FindNext(T v) {
		return t.lower_bound(make_pair(v+1, 0))->first;
	}
};

int main() {
	MultiSet<int, less<int> > se;
    int n;
    scanf("%d", &n);
    while (n--) {
        int op, x;
        scanf("%d%d", &op, &x);
        switch (op) {
        case 1:
            se.Insert(x);
            break;
        case 2:
            se.Delete(x);
            break;
        case 3:
            printf("%lu\n", se.RankOf(x));
            break;
        case 4:
            printf("%d\n", se.FindByRank(x));
            break;
        case 5:
            printf("%d\n", se.FindPre(x));
            break;
        case 6:
            printf("%d\n", se.FindNext(x));
            break;
        }
    }
    return 0;
}