【模板】【数据结构】【树】主席树

技巧一:离散去重

for(int i=1;i<=n;i++) scanf("%d",&a[i] ),b[i]=a[i];
    sort(b+1,b+n+1);
    int nn=unique(b+1,b+n+1)-b-1;//假设有x个数,那么nn指针会停在第x+1个数的位置 ,nn及以后的都是重复的元素for(int i=1;i<=n;i++)
        id[i]=lower_bound(b+1,b+nn+1,a[i])-b;//离散过后的新value

技巧二:可持久化数据结构

修改被影响的部分,然后用指针指向新的点,记录新的点,就可以方便查找了

void updata(int l,int r,int &nw,int pre,int x)
{
    nw=++cnt;
    t[nw]=t[pre];t[nw].sum ++;
    if(l==r) return ;
    int mid=(l+r)>>1;
    if(mid>=x) updata(l,mid,t[nw].lc ,t[pre].lc ,x);
    else updata(mid+1,r,t[nw].rc ,t[pre].rc ,x);
}

技巧三:区间问题一般都可以被拆成a[R]-a[L-1]

即使每个a有N个分支

int query(int l,int r,int ll,int rr,int kk)
{
    if(l==r) return l;
    int s=t[t[rr].lc ].sum -t[t[ll].lc ].sum ;
    int mid=(l+r)>>1;
    if(s>=kk) return query(l,mid,t[ll].lc ,t[rr].lc ,kk);
    else return query(mid+1,r,t[ll].rc ,t[rr].rc ,kk-s);
}

最后:主席树模板

//luogu P3834
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n,m;
const int N=200003;
int a[N],b[N],id[N];

struct node
{
    int sum,lc,rc;
}t[N*40];
int cnt,rt[N];
int build(int l,int r)
{
    int rt=++cnt;
    t[rt].sum =0;
    if(l!=r)
    {
        int mid=(l+r)>>1;
        t[rt].lc =build(l,mid);
        t[rt].rc =build(mid+1,r);
    }
    return rt;
}
void updata(int l,int r,int &nw,int pre,int x)
{
    nw=++cnt;
    t[nw]=t[pre];t[nw].sum ++;
    if(l==r) return ;
    int mid=(l+r)>>1;
    if(mid>=x) updata(l,mid,t[nw].lc ,t[pre].lc ,x);
    else updata(mid+1,r,t[nw].rc ,t[pre].rc ,x);
}

int query(int l,int r,int ll,int rr,int kk)
{
    if(l==r) return l;
    int s=t[t[rr].lc ].sum -t[t[ll].lc ].sum ;
    int mid=(l+r)>>1;
    if(s>=kk) return query(l,mid,t[ll].lc ,t[rr].lc ,kk);
    else return query(mid+1,r,t[ll].rc ,t[rr].rc ,kk-s);
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i] ),b[i]=a[i];
    sort(b+1,b+n+1);
    int nn=unique(b+1,b+n+1)-b-1;//假设有x个数,那么nn指针会停在第x+1个数的位置
    //去重,离散
    rt[0]=build(1,nn);
    for(int i=1;i<=n;i++)
    {
        id[i]=lower_bound(b+1,b+nn+1,a[i])-b;
        updata(1,nn,rt[i],rt[i-1],id[i]);//需要a数组的数到序号的离散
    }//离散过后的新value
    int x,y,k;
    while(m--)
    {
        scanf("%d%d%d",&x,&y,&k);
        printf("%d\n",b[ query(1,nn,rt[x-1],rt[y],k) ]);//需要序号到b数组的离散
    }
    return 0;
}

原文地址:https://www.cnblogs.com/xwww666666/p/11270249.html

时间: 2024-10-10 09:42:07

【模板】【数据结构】【树】主席树的相关文章

可持久化数据结构之主席树

转自:http://finaltheory.info/?p=249 HomeACM可持久化数据结构之主席树 06十2013 可持久化数据结构之主席树 Written by FinalTheory on. Posted in ACM 引言 首先引入CLJ论文中的定义: 所谓的“持久化数据结构”,就是保存这个数据结构的所有历史版本,同时利用它们之间的共用数据减少时间和空间的消耗. 本文主要讨论两种可持久化线段树的算法思想.具体实现以及编码技巧. 核心思想 可持久化线段树是利用函数式编程的思想,对记录

可持久化线段树--主席树

浅谈可持久化线段树--主席树 权值线段树 权值线段树和普通线段树不一样的地方就是在于 它的结点存储的是区间内数的个数 这个线段树的好处就在于我们可以根据 左子树 和 右子树 的大小从而进行 查找某个数的排名 或者 查找排名为rk的数 可持久化的含义 可持久数据结构主要指的是我们可以查询历史版本的情况并支持插入,利用使用之前历史版本的数据结构来减少对空间的消耗(能够对历史进行修改的是函数式). 主席树的建树过程: 最开始的时候就是一个空树 然后我们再插入一个元素3 再加入一个元素 1 模版一 :求

hdu 2665 可持久化线段树求区间第K大值(函数式线段树||主席树)

http://acm.hdu.edu.cn/showproblem.php?pid=2665 Problem Description Give you a sequence and ask you the kth big number of a inteval. Input The first line is the number of the test cases. For each test case, the first line contain two integer n and m (

bzoj2223 [Coci 2009]PATULJCI (模板)(主席树)

2223: [Coci 2009]PATULJCI Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1245  Solved: 530[Submit][Status][Discuss] Description HINT 输入第二个整数是序列中权值的范围Lim,即1<=ai(1<=i<=n)<=Lim,1<=Lim<=10000. 主席树模板dearu: 蒟蒻只能码板子了啊(摊): ↓代码 1 #include<ios

【重码数据结构】主席树(可持久化线段树)

例题:https://www.luogu.org/problemnew/show/P3834 主席树用于查询每个历史版本. 这个题代码如下 #include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=200001; int n,m,tot; ll a[maxn],b[maxn]; struct stree{ int lc,rc; ll sum; #define lc(x) tree[x].lc

数据结构(主席树):HZOI 2016 采花

[题目描述] 给定一个长度为n,包含c种颜色的序列,有m个询问,每次给出两个数l,r,表示询问区间[l,r]中有多少种颜色的出现次数不少于2次. 本题强制在线,对输入的l,r进行了加密,解密方法为: l = l' xor lastans r = r' xor lastans 其中l', r'为输入的l和r,xor表示异或,lastans为上一次询问的答案且初始值为0. [输入格式] 第一行三个正整数n,c,m,意义与题目描述中的相同. 第二行n个位于[1,c]内的正整数,表示序列上每个位置的颜色

数据结构之主席树

这里先讲静态的主席树,关于静态区间第k小.(有兴趣的朋友还可以去看看我写的整体二分,代码实现略优于主席树我觉得,当然静态主席树是很好写的) 题目描述: 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出格式 输入格式: 第一行包含两个正整数N.M,分别表示序列的长度和查询的个数. 第二行包含N个正整数,表示这个序列各项的数字. 接下来M行每行包含三个整数 l, r, kl,r,k , 表示查询区间 [l, r][l,r] 内的第k小值. 输出格式: 输

小结:线段树 &amp; 主席树

概要: 就是用来维护区间信息,然后各种秀智商游戏. 应用: 优化dp.主席树等. 技巧及注意: size值的活用:主席树就是这样来的.支持区间加减,例题和模板:主席树,[BZOJ]1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树),[BZOJ]1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套可持久化线段树(主席树)) 01(就是更新和不更新等这种对立操作)情况:我们就要在各个更新的操作中明白

bzoj 3545&amp;&amp;3551: [ONTAK2010]Peaks &amp;&amp;加强版 平衡树&amp;&amp;并查集合并树&amp;&amp;主席树

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Status] Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. I

[BZOJ4539][HNOI2016]树(主席树)

4539: [Hnoi2016]树 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 746  Solved: 292[Submit][Status][Discuss] Description 小A想做一棵很大的树,但是他手上的材料有限,只好用点小技巧了.开始,小A只有一棵结点数为N的树,结点的编号为1,2,-,N,其中结点1为根:我们称这颗树为模板树.小A决定通过这棵模板树来构建一颗大树.构建过程如下:(1)将模板树复制为初始的大树.(2)以下(2