主席树算法解析

主席树

感想:

这个主席树我还是学了接近一周了,虽然思想懂得比较快,但是一直比较浮躁,所以

一直都没有静下来去看代码,但是在一周的慢慢消化中,我还是懂了主席树的思想和代码

,我也看了其他大牛的博客,都写的很好,所以我的这一篇都是比较水的

主席树是线段树的一种分支,可以解决一道题中的历史遗留问题或者第几大

例如:1,2,5,3,2,2,3,4

求区间 【3,7】中的第三小的数字,我们可以很容易的看出是3

然后这样一种类型其实就是主席树的模板题了

推荐模板题:poj2104

Poj2761

Hdu2665

算法:我的语言形容能力不好,我就尽量用图来表达吧

定义的量:

T[],sum[],R[],L[],a[],b[],d,tot,rt

T[]:第几棵树的含有的数字个数

Sum[i]:节点i含有的数字个数

L[i]:节点i的左边界

R[i]:节点i的右边界

d:去重后数组剩下的个数

Tot:最后的节点总数

1.首先我们建立一棵空树,里面每一个节点都是0

2.然后向里面加点,我们先挨着建树,没有优化,每一个节点存的是区间里的数字个数

3.用一个优化的图,这种方式不会爆内存(因为画完的话占的面积太大,所以我就举例子加入第8个点时,即树7向树8转换)

树8就是除去蓝色斜杠杠掉的节点

4.假如我们要求区间[3,7]第3小,我们就用树7去减树2再来看(l,r区间求法是:t[r]-t[l-1])

5.接着在这棵树上不断判断mid和k的关系,找到第k小

这就是这个主席树了,我们接着来看代码

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #define maxn 100005
 8 using namespace std;
 9
10 int sum[maxn<<5],L[maxn<<5],R[maxn<<5],t[maxn<<5];
11 int tot,d,x,m,n,a[maxn],b[maxn];
12
13 int build(int l,int r)//在这个问题里,这一步实际意义不大,就是建立空树
14 {//                      主要是累加tot
15     int rt=(++tot);
16     int m=(l+r)>>1;
17     sum[rt]=0;
18     if(l<r)
19     {
20         build(l,m);
21         build(m+1,r);
22     }
23     return rt;
24 }
25
26 int update(int pre,int l,int r,int x)
27 {
28     int rt=(++tot);
29     L[rt]=L[pre];R[rt]=R[pre];sum[rt]=sum[pre]+1;
30     if(l<r)
31     {
32         int m=(l+r)>>1;
33         if(x<=m)L[rt]=update(L[pre],l,m,x);//需要变更的链
34         else R[rt]=update(R[pre],m+1,r,x);
35     }
36     return rt;
37 }
38
39 int query(int u,int v,int l,int r,int k)
40 {
41     if(l>=r)return l;
42     int m=(l+r)>>1;
43     int num=sum[L[v]]-sum[L[u]];//两棵树对应节点相减
44     if(num>=k){//左边已经到了第num名
45         return query(L[u],L[v],l,m,k);
46     }else return query(R[u],R[v],m+1,r,k-num);
47
48 }
49
50 int main()
51 {
52     scanf("%d%d",&n,&m);
53     for(int i=1;i<=n;i++)
54     {
55         scanf("%d",&a[i]);
56         b[i]=a[i];
57     }
58     sort(b+1,b+n+1);
59     int d=unique(b+1,b+n+1)-(b+1);//去重后的数字个数
60     t[0]=build(1,d);
61     for(int i=1;i<=n;i++)
62     {
63         int x=lower_bound(b+1,b+d+1,a[i])-b;
64         t[i]=update(t[i-1],1,d,x);
65     }
66     for(int j=1;j<=m;j++)
67     {
68         int l,r,k;
69         scanf("%d%d%d",&l,&r,&k);
70         int y=query(t[l-1],t[r],1,d,k);//求l,r区间就是树r减去l-1
71         printf("%d\n",b[y]);
72     }
73
74 } 

PS:第一次发这么长的帖子,可能会有很多瑕疵,希望诸位大佬指出

时间: 2024-10-20 09:00:46

主席树算法解析的相关文章

Spark机器学习(6):决策树算法

1. 决策树基本知识 决策树就是通过一系列规则对数据进行分类的一种算法,可以分为分类树和回归树两类,分类树处理离散变量的,回归树是处理连续变量. 样本一般都有很多个特征,有的特征对分类起很大的作用,有的特征对分类作用很小,甚至没有作用.如决定是否对一个人贷款是,这个人的信用记录.收入等就是主要的判断依据,而性别.婚姻状况等等就是次要的判断依据.决策树构建的过程,就是根据特征的决定性程度,先使用决定性程度高的特征分类,再使用决定性程度低的特征分类,这样构建出一棵倒立的树,就是我们需要的决策树模型,

我的Android进阶之旅------&gt;解决Jackson、Gson解析Json数据时,Json数据中的Key为Java关键字时解析为null的问题

1.问题描述 首先,需要解析的Json数据类似于下面的格式: { ret: 0, msg: "normal return.", news: [ { id: "NEW2016062800875700", from: "腾讯新闻客户端", qqnews_download_url: "http://inews.qq.com/m?refer=openapi_for_xiaotiancai", articletype: "1&

Spark机器学习解析下集

上次我们讲过<Spark机器学习(上)>,本文是Spark机器学习的下部分,请点击回顾上部分,再更好地理解本文. 1.机器学习的常见算法 常见的机器学习算法有:l   构造条件概率:回归分析和统计分类:l   人工神经网络:l   决策树:l   高斯过程回归:l   线性判别分析:l   最近邻居法:l   感知器:l   径向基函数核:l   支持向量机:l   通过再生模型构造概率密度函数:l   最大期望算法:l   graphical model :包括贝叶斯网和 Markov 随机

可持久化线段树(主席树)新手向教程

嗯今天来讲讲一个高端玩意,叫可持久化线段树. 新手向,有点耐心是一定可以懂的 知识储备 首先你得知道线段树是什么,不然也不需要学这个东西 线段树 引入 现在呢我们来思考一个问题,如果题目有需要保存线段树更改前的各个历史版本(比如给一个数列的前n项各建一棵线段树),我们应该怎么存? 每个版本存一棵树吗? 不不不太多了会爆空间的QAQ 事实上,如果要存储前我们只需要修改少量点就可以,因为每两个版本间有很多的重复部分. 解析 圈里面是这个区间包含的数字在数列里出现的次数. 比如:现在我们有数列 2 1

金灿荣解析特朗普上台后中美新型大国关系的机遇与挑战

金灿荣解析特朗普上台后中美新型大国关系的机遇与挑战(文字+视频) 2016.12.24 晴朗 阅读 1971 [导读]资深美国问题专家.中国人民大学国际关系学院副院长金灿荣教授2016年12月16日在东南卫视<中国正在说>节目解读了中美关系的走向.这位被网民赞誉为"金五刀"的金教授以他特有的幽默和锐利道出了中美关系背后的实质性角力变化. 一.当前形势与原因 2016年是1991年苏联解体25年以来最为混乱的一年,欧洲面临恐怖袭击和难民的双重压力,土耳其政变,英国脱欧,巴西政

柴赛特刊丨访第16届“柴赛”钢琴组评委会主席-丹尼斯&#183;马祖耶夫

对话“柴赛”大师 备受全球音乐圈和爱乐者高度关注的第16届柴可夫斯基国际音乐比赛(简称“柴赛”)完美落下帷幕.比赛期间,作为第16届“柴赛”钢琴组评委会主席的Denis Matsuev(丹尼斯·马祖耶夫)接受了CCTV.中新社.中俄资讯网等多家媒体的联合采访.这位享誉世界的“钢琴大师”畅所欲言,讲述只属于本届柴可夫斯基钢琴大赛的精彩故事. 谈柴可夫斯基钢琴大赛独有特色 议中国选手大赛表现 评指定用琴中国“长江钢琴” 丹尼斯·马祖耶夫畅所欲言 全面解析本届柴可夫斯基钢琴大赛 精彩阐述对钢琴艺术的独

C++工程编译之“error LNK2001: 无法解析的外部符号”

今天一整天都在折腾“error LNK2001: 无法解析的外部符号”,就在头疼不已的时候,总算是找到问题原因了:各个动态链接库的编译方式必须统一才行,要不然很容易对库函数的引用产生冲突.简单来说就是,如果使用的第三方函数库编译方式采用/MD,那么主工程也应该使用/MD.我使用了libevent,而主工程默认采用/MT,所以需要忽略一大堆的函数库,我还纳闷呢,怎么会这么奇怪!!今天总算是解决了长久以来的困惑了. 下面引用一篇文章的描述:[Z]VC运行库版本不同导致链接.LIB静态库时发生重复定义

防止恶意解析——禁止通过IP直接访问网站

一.什么是恶意解析 一般情况下,要使域名能访问到网站需要两步,第一步,将域名解析到网站所在的主机,第二步,在web服务器中将域名与相应的网站绑定.但是,如果通过主机IP能直接访问某网站,那么把域名解析到这个IP也将能访问到该网站,而无需在主机上绑定,也就是说任何人将任何域名解析到这个IP就能访问到这个网站.可能您并不介意通过别人的域名访问到您的网站,但是如果这个域名是未备案域名呢?一旦被查出,封IP.拔线甚至罚款的后果都是需要您来承担的.某些别有用心的人,通过将未备案域名解析到别人的主机上,使其

.NET深入解析LINQ框架(五:IQueryable、IQueryProvider接口详解)

阅读目录: 1.环路执行对象模型.碎片化执行模型(假递归式调用) 2.N层对象执行模型(纵横向对比链式扩展方法) 3.LINQ查询表达式和链式查询方法其实都是空壳子 4.详细的对象结构图(对象的执行原理) 5.IQueryable<T>与IQueryProvider一对一的关系能否改成一对多的关系 6.完整的自定义查询 1]. 环路执行对象模型.碎片化执行模型(假递归式调用) 这个主题扯的可能有点远,但是它关系着整个LINQ框架的设计结构,至少在我还没有搞懂LINQ的本意之前,在我脑海里一直频