zoukankan      html  css  js  c++  java
  • 洛谷P3834【模板】可持久化线段树 1(主席树)

    题目背景

    这是个非常经典的主席树入门题——静态区间第K小

    数据已经过加强,请使用主席树。同时请注意常数优化

    题目描述

    如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值。

    输入输出格式

    输入格式:

    第一行包含两个正整数N、M,分别表示序列的长度和查询的个数。

    第二行包含N个正整数,表示这个序列各项的数字。

    接下来M行每行包含三个整数(l, r, k) , 表示查询区间([l, r])内的第k小值。

    输出格式:

    输出包含k行,每行1个正整数,依次表示每一次查询的结果

    输入输出样例

    输入样例#1:

    5 5
    25957 6405 15770 26287 26465
    2 2 1
    3 4 1
    4 5 1
    1 2 2
    4 4 1

    输出样例#1:

    6405
    15770
    26287
    25957
    26287

    说明

    数据范围:

    对于20%的数据满足:(1 leq N, M leq 10)

    对于50%的数据满足:(1 leq N, M leq 10^3)

    对于80%的数据满足:(1 leq N, M leq 10^5)

    对于100%的数据满足:(1 leq N, M leq 2cdot 10^5)

    对于数列中的所有数(a_i)​ ,均满足(-{10}^9 leq a_i leq {10}^9)

    样例数据说明:

    N=5,数列长度为5,数列从第一项开始依次为([25957, 6405, 15770, 26287, 26465 ])

    第一次查询为([2, 2])区间内的第一小值,即为6405

    第二次查询为([3, 4])区间内的第一小值,即为15770

    第三次查询为([4, 5]) 区间内的第一小值,即为26287

    第四次查询为([1, 2])区间内的第二小值,即为25957

    第五次查询为([4, 4]) 区间内的第一小值,即为26287

    题解

    可持久化线段树模板题。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <vector>
    inline int max(int a, int b){return a > b ? a : b;}
    inline int min(int a, int b){return a < b ? a : b;}
    inline void swap(int &x, int &y){int  tmp = x;x = y;y = tmp;}
    inline void read(int &x)
    {
        x = 0;char ch = getchar(), c = ch;
        while(ch < '0' || ch > '9') c = ch, ch = getchar();
        while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
        if(c == '-') x = -x;
    }
    
    const int INF = 0x3f3f3f3f;
    const int MAXN = 200000 + 10;
    
    struct Node
    {
    	int ls, rs, size;
    	void clear(){ls = rs = size = 0;}
    }node[MAXN * 40];
    int n, m, stack[MAXN], top, tot, num[MAXN], cnt, fa[MAXN], pos[MAXN];
    int newnode(){if(top) return stack[top --];return ++ tot;}
    void delnode(int x){stack[++ top] = x;node[x].clear();}
    struct Tmp{int rank,num;}tmp[MAXN];
    bool cmp(Tmp a, Tmp b){return a.num < b.num;}
    inline void pushup(int x){node[x].size = node[node[x].ls].size + node[node[x].rs].size;}
    void build(int &o, int l = 1, int r = cnt)
    {
    	if(!o) o = newnode();
    	if(l == r)	return;
    	int mid = (l + r) >> 1;
    	build(node[o].ls, l, mid);
    	build(node[o].rs, mid + 1, r);
    }
    void insert(int &o, int oo, int p, int l = 1, int r = cnt)
    {
    	if(!o) o = newnode();
    	node[o].size = node[oo].size + 1; 
    	if(l == r)	return;
    	int mid = (l + r) >> 1;
    	if(p <= mid) insert(node[o].ls, node[oo].ls, p, l, mid), node[o].rs = node[oo].rs;
    	else insert(node[o].rs, node[oo].rs, p, mid + 1, r), node[o].ls = node[oo].ls;
    }
    //l-1->o,r->oo, 第k小 
    int ask(int o, int oo, int k, int l = 1, int r = cnt)
    {
    	if(l == r) return l;
    	int mid = (l + r) >> 1, a = node[node[oo].ls].size - node[node[o].ls].size;
    	if(a >= k) return ask(node[o].ls, node[oo].ls, k, l, mid);
    	else return ask(node[o].rs, node[oo].rs, k - a, mid + 1, r);
    }
    int main()
    {
    	read(n), read(m);
    	for(int i = 1;i <= n;++ i) read(tmp[i].num), tmp[i].rank = i;
    	std::sort(tmp + 1, tmp + 1 + n, cmp);
    	tmp[0].num = -INF;
    	for(int i = 1;i <= n;++ i)
    	{
    		if(tmp[i].num > tmp[i - 1].num) ++ cnt, pos[cnt] = tmp[i].num;
    		num[tmp[i].rank] = cnt;
    	}
    	build(fa[0]);
    	for(int i = 1;i <= n;++ i) insert(fa[i], fa[i - 1], num[i]);
    	for(int i = 1;i <= m;++ i)
    	{
    		int l, r, k;read(l), read(r), read(k);
    		printf("%d
    ", pos[ask(fa[l - 1], fa[r], k)]);
    	}
     	return 0;
    }
    
  • 相关阅读:
    解决pydev无法增加jython271 interpreter的问题
    使用pygal 做chart图的经验分享
    python4delphi 使用
    Some Delphi tips
    http request method and response codes
    flask 项目的开发经验总结
    解决pydev报unsolved import的问题
    python __future__ package的几个特性
    用一个简单的例子来理解python高阶函数
    正确地组织python项目的结构
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8854938.html
Copyright © 2011-2022 走看看