zoukankan      html  css  js  c++  java
  • hdu2665(主席树模板题)

    hdu2665

    题意

    求区间第 k 小。

    分析

    参考
    这类题目做法挺多的,例如 划分树
    这里使用主席树再写一发,不得不说主席树相比而言要好写的多,比起普通线段树,主席树就是复用了线段树共有的信息。
    可持久化数据结构讲究的就是复用共有的信息,可持久化 Trie 的思想也是差不多的。

    code

    #include<bits/stdc++.h>
    using namespace std;
    #define lson l, m
    #define rson m + 1, r
    const int MAXN = 1e5 + 10;
    int L[MAXN << 5], R[MAXN << 5], sum[MAXN << 5];
    int tot;
    int a[MAXN], f[MAXN], h[MAXN];
    int build(int l, int r) {
        int rt = ++tot;
        sum[rt] = 0;
        if(l < r) {
            int m = l + r >> 1;
            L[rt] = build(lson);
            R[rt] = build(rson);
        }
        return rt;
    }
    int update(int pre, int l, int r, int x) {
        int rt = ++tot;
        L[rt] = L[pre];
        R[rt] = R[pre];
        sum[rt] = sum[pre] + 1; // 先继承前面的线段树
        if(l < r) {
            int m = l + r >> 1;
            if(x <= m) L[rt] = update(L[pre], lson, x); // 因为右边不需要更新,所以覆盖掉左边
            else R[rt] = update(R[pre], rson, x); // 同理
        }
        return rt;
    }
    int query(int ql, int qr, int l, int r, int k) { // 区间[ql, qr]从小到大排序后正数第 k 个数
        if(l >= r) return l;
        int m = l + r >> 1;
        int num = sum[L[qr]] - sum[L[ql]];
        if(num >= k) return query(L[ql], L[qr], lson, k); // 左边至少有 k 个数
        else return query(R[ql], R[qr], rson, k - num);
    }
    int main() {
        int T;
        scanf("%d", &T);
        while(T--) {
            int n, m; tot = 0;
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; i++) {
                scanf("%d", &a[i]);
                h[i] = a[i];
            }
            sort(h + 1, h + 1 + n);
            int d = unique(h + 1, h + 1 + n) - h - 1;
            f[0] = build(1, d);
            for(int i = 1; i <= n; i++) {
                int x = lower_bound(h + 1, h + 1 + d, a[i]) - h;
                f[i] = update(f[i - 1], 1, d, x);
            }
            while(m--) {
                int l, r, k;
                scanf("%d%d%d", &l, &r, &k);
                int x = query(f[l - 1], f[r], 1, d, k);
                printf("%d
    ", h[x]);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    用C++实现网络编程---抓取网络数据包的实现方法
    UNICODE字符串与多字节字符串的转换
    MFC ComboBox的使用
    Windows API学习---线程与内核对象的同步
    Windows API学习---用户方式中的线程同步
    MFC读取XML文件并解析
    Windows API学习---插入DLL和挂接API
    常用[js,css,jquery,html]
    JDBC链接MySQL和Oracle
    使用.NET MVC框架项目开发流程(项目开发流程)
  • 原文地址:https://www.cnblogs.com/ftae/p/7668564.html
Copyright © 2011-2022 走看看