zoukankan      html  css  js  c++  java
  • [模板]主席树及其应用

    可持久化权值线段树;

    root数组记录第i版本根, 每次建树时只新建当前位相关子节点, 不相关子节点直接用上一版本的原节点

    有前缀和及权值树性质, 可区间查询k小数


    1.查询区间第k小

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
     
    const int MAXN = 1e5 + 10;
    
    struct prt
    {
    	struct node { int lson, rson, num;} T[MAXN * 40];
    	int root[MAXN], cnt;
    	prt() { cnt = 0; }
    	
    	void update(int l, int r, int &now, int pre, int a) //新建一支 
    	{ 
    	    now = ++cnt;
    	    T[now] = T[pre];
    	    T[now].num++;
    	    if(l == r) return ;
    	    int mid = (l + r) >> 1;
    	    if(a <= mid) update(l, mid, T[now].lson, T[pre].lson, a);
    	    else update(mid + 1, r, T[now].rson, T[pre].rson, a);
    	}
    	
    	int query(int l, int r, int now, int pre, int k) //查询区间排名为K的映射元素值 
    	{
    	    if(l == r) return l;
    	    int mid = (l + r) >> 1;
    	    int lnum = T[T[now].lson].num - T[ T[pre].lson ].num;
    	    if(k <= lnum) return query(l, mid,T[now].lson, T[pre].lson, k);
    	    else return query(mid + 1, r, T[now].rson, T[pre].rson, k - lnum);
    	}	
    };
     
    struct lsh
    {
    	int v[MAXN], vl; 
    	lsh() { vl = 0; }
    	void pb(int val) { v[vl++] = val; } //向后加元素 
    	void init() { sort(v, v + vl); vl = unique(v, v + vl) - v; } //初始化排序,重置大小 
    	int find(int val) { return lower_bound(v, v + vl, val) - v;} //查找元素下标
    	int get(int pos) { return v[pos]; }  //通过下标返回元素 
    };
    
    int a[MAXN];
     
    int main()
    {
    	int t;
    	scanf("%d", &t);
    	while(t--)
    	{
    		int n, m;
     		scanf("%d%d", &n, &m);
    	    lsh V;
    	    prt T;
    	    for(int i = 1; i <= n; i++)
    	    {
    	    	scanf("%d", &a[i]);
    	    	V.pb(a[i]);
    		}
    	    
    	    V.init();
    	    
    	    for(int i = 1; i <= n; i++)
    	        T.update(0, n, T.root[i], T.root[i - 1], V.find(a[i]));
    	    
    	    int a, b, k;
    	 	
    	    for(int i = 1; i <= m; i++)
    	    {
    	        scanf("%d%d%d", &a, &b, &k);
    	        printf("%d
    ", V.get( T.query(0, n, T.root[b], T.root[a - 1], k) ) );
    	    }	
    	}
        
     
        return 0;
    }
    
  • 相关阅读:
    0601 新的冲刺
    0527 演示内容
    0525 项目回顾7.0
    0523 Scrum项目6.0
    0518 Scrum项目5.0
    Scrum 4.0
    0512 操作系统进程调度实验
    0511 backlog 项目管理
    复利计算器之单元测试
    操作系统的实验一实验报告
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270362.html
Copyright © 2011-2022 走看看