• 主席树初步 HDU2665的区间第k小


    首先看一下这个人的blog吧,讲的精炼 http://blog.sina.com.cn/s/blog_4a0c4e5d0101c8fr.html

    然后再推荐一下这个人的blog:http://www.cnblogs.com/zinthos/p/3899565.html

    这两个博客看了就差不多了。

    自己说一下对代码的理解吧。

    就是每一个数字开一个空间,然后每个空间用tot标号,最后tot就是总体开的数目。然后不同的线段树可能有相同的左儿子或者右二子(或者左=右,右=左),然后具体都是通过tot的储存值表现出来,大致就是这样吧。

    代码挺裸的:

    //看看会不会爆int! 或者绝对值问题。
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define LL long long
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define ALL(a) a.begin(), a.end()
    const int maxn = 100000 + 5;
    struct Segment{
        int lb, rb;
        int cnt;
        Segment(int l = 0, int r = 0, int c = 0): lb(l), rb(r), cnt(c){}
    }s[maxn * 20];
    int root[maxn];
    int a[maxn];
    int n, m, tot;
    
    int buildtree(int l, int r){
        int k = tot++;
        if (l == r){
            s[k] = Segment(0, 0, 0);
            return k;
        }
        int mid = (l + r) / 2;
        if (mid >= l) s[k].lb = buildtree(l, mid);
        else s[k].rb = buildtree(mid + 1, r);
        return k;
    }
    
    inline void push_up(int o){
        s[o].cnt = s[s[o].lb].cnt + s[s[o].rb].cnt;
    }
    
    int update(int o, int l, int r, int pos, int val){
        int k = tot++;
        s[k] = s[o];
        if (l == r && l == pos){
            s[k].cnt += val;
            return k;
        }
        int mid = (l + r) / 2;
        if (mid >= pos) s[k].lb = update(s[o].lb, l, mid, pos, val);
        else s[k].rb = update(s[o].rb, mid + 1, r, pos, val);
        push_up(k);
        return k;
    }
    
    int query(int o1, int o2, int l, int r, int num){
        if (l == r) return l;
        int mid = (l + r) / 2;
        int res = s[s[o1].lb].cnt - s[s[o2].lb].cnt;
        if (res >= num) return query(s[o1].lb, s[o2].lb, l, mid, num);
        else return query(s[o1].rb, s[o2].rb, mid + 1, r, num - res);
    }
    
    int main(){
        while (scanf("%d%d", &n, &m) == 2){
            vector<int> v(n);
            for (int i = 1; i <= n; i++){
                scanf("%d", a + i);
                v[i - 1] = a[i];
            }
            sort(ALL(v));
            v.erase(unique(ALL(v)), v.end());
            for (int i = 1; i <= n; i++){
                a[i] = lower_bound(ALL(v), a[i]) - v.begin() + 1;
            }
            tot = 0; int len = v.size();
            root[0] = buildtree(1, len);
            for (int i = 1; i <= n; i++){
                root[i] = update(root[i - 1], 1, len, a[i], 1);
            }
            for (int i = 1; i <= m; i++){
                int l, r, num;
                scanf("%d%d%d", &l, &r, &num);
                int pos = query(root[r], root[l - 1], 1, len, num);
                printf("%d
    ", v[pos - 1]);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    php包含(include/require)文件时的作用域
    Android使用DrawerLayout仿qq6.6版本侧滑效果
    Android几种强大的下拉刷新库
    Android 捕捉app系统中未处理的异常
    Android中内存泄露与如何有效避免OOM总结
    Android进程间的通信之Messenger
    Android中Parcelable接口用法
    《完美解决系列》Android5.0以上 Implicit intents with startService are not safe
    Android高效加载大图、多图解决方案,有效避免程序OOM
    使用真机导致Androidstudio打印不出log
  • 原文地址:https://www.cnblogs.com/heimao5027/p/5853159.html
Copyright © 2020-2023  润新知