题目链接

学习了一下主席树,感觉具体算法思路不大好讲。。

大概是先建个空线段树,然后类似于递推,每一个都在前一个“历史版本”的基础上建立一个新的“历史版本”,每个历史版本只需占用树高个空间(好神奇!)

查询时这道题是通过“历史版本”间作差解决

*另外提一下,在建立“历史版本”的过程中,是“新建”,而不是“更新”,是先copy过来原有的,再按个人需求改成自己的,所产生的一个新的“历史版本”

希望注释能有帮助

//吐槽一下,本人看kuangbin模板看得好费劲,一方面不习惯用lson[],rson[]数组搞线段树,另一方面他的update query函数都是用二分写的,看半天没理解。。。

以下是按个人习惯加了注释的代码

#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#define M 100000+5
using namespace std;  const int N=1e5+7;
const int INF=0x3f3f3f3f;struct node
{int l,r;    //l,r分别指向左右孩子,但由于历史的错乱,二者的值未必有规律 int size;    //当前历史版本里,该节点中所包含的元素个数//p.s. 在最后一个历史版本里,size即为总元素个数n
}tr[N*20];
//主席树的初始状态为一“空架子”
//每次updata都在前一“历史版本”基础上新建h个结点,共updata n次,产生了n个历史版本,每个版本占用空间为h*sizeof(one node)
int tot;    //结点建立顺序|所赋标号 int n;        //共n个数
int a[N];    //读入数组
int root[N];//记录a[]中每一个数对应各“历史版本”在主席树中的根结点标号
int m;        //t[]中元素个数
int t[N];    //离散数组
int pos(int x)
{return lower_bound(t+1,t+1+m,x)-t;
}
int q;        //q个询问int build(int l,int r)
{int rt=tot++;tr[rt].size=0;if(l==r) return rt;int mid=(l+r)>>1;tr[rt].l=build(l,mid);tr[rt].r=build(mid+1,r);return rt;
}//    pre_node:最近一历史,[l,r]当前所更新到的包含x的区间
//    x此次更新的“终点”
//    沿途要增加的“权值”
//    p.s.  1<=l<=r<=m
int updata(int pre_node,int l,int r,int x,int v)
{int rt=tot++;            //rt为新结点的标号 tr[rt]=tr[pre_node];    //先拷贝原指向当前区间的结点tr[rt].size+=v;//    在函数不断向下深入过程中,更新node.size if(l==r) return rt;int mid=(l+r)>>1;if(x<=mid)    tr[rt].l=updata(tr[pre_node].l,l,mid,x,v);else    tr[rt].r=updata(tr[pre_node].r,mid+1,r,x,v);return rt;//    在函数逐步return过程中,更新node.l|r
}//    ql,qr反应的是在a[]中的下标,对应着更新到该下标时的“历史版本”
//    l,r反应的是在t[]中的下标
int query(int ql,int qr,int l,int r,int k)
{if(l==r) return l;int diff=tr[tr[qr].l].size-tr[tr[ql].l].size;//在更新到ql位置和更新到qr位置时两个“历史版本”下左孩子的size之差// p.s. size的大小反应较小数的多少 int mid=(l+r)>>1;if(diff>=k) return query(tr[ql].l,tr[qr].l,l,mid,k);else return  query(tr[ql].r,tr[qr].r,mid+1,r,k-diff);
}
int main()
{while(~scanf("%d%d",&n,&q)){for(int i=1;i<=n;i++)scanf("%d",&a[i]),t[i]=a[i];sort(t+1,t+1+n);m=unique(t+1,t+1+n)-t-1;m++,t[m]=INF;tot=0;root[0]=build(1,m);    //初始化一个空线段树for(int i=1;i<=n;i++){int order=pos(a[i]);root[i]=updata(root[i-1],1,m,order,1);//每次在上一次已完成的基础上新增h个结点 //从根 逐步新建结点到 a[i]在线段树上所对应的位置 //在这个逐步新建结点的过程中,要新建的结点的l,r始终满足l<=m<=r//这些结点每一个的size都在pre_node的基础上+1
        }while(q--){int l,r,k;scanf("%d%d%d",&l,&r,&k);printf("%d\n",t[query(root[l-1],root[r],1,m,k)]); } }
}

转载于:https://www.cnblogs.com/Just--Do--It/p/6523238.html

poj 2104: K-th Number 【主席树】相关推荐

  1. poj2104 k-th number 主席树入门讲解

    poj2104 k-th number 主席树入门讲解 定义:主席树是一种可持久化的线段树 又叫函数式线段树   刚开始学是不是觉得很蒙逼啊 其实我也是 主席树说简单了 就是 保留你每一步操作完成之后 ...

  2. POJ 2104 K-th Number 主席树(区间第k大)

    题目链接: http://poj.org/problem?id=2104 K-th Number Time Limit: 20000MSMemory Limit: 65536K 问题描述 You ar ...

  3. POJ - 2104 K-th Number(主席树)

    题目链接:点击查看 题目大意:给出一个数列,然后是m次查询,每次查询闭区间[l,r]内第K大的数 题目分析:裸的主席树,暑假集训第三周的时候就听说过了这个数据结构,不过当时太懒了,而且那些主席树的问题 ...

  4. K-th Closest Distance HDU - 6621(第k小绝对值+主席树+二分)

    You have an array: a1, a2, , an and you must answer for some queries. For each query, you are given ...

  5. 【HDU - 2665】Kth number(区间第K大,主席树,模板)

    题干: Give you a sequence and ask you the kth big number of a inteval. Input The first line is the num ...

  6. 主席树学习小结(POJ 2104)

    在高中的时候就听到过主席树了,感觉非常高端,在寒假的时候 winter homework中有一题是查找区间第K大的树,当时就开始百度这种网上的博客,发现主席树看不懂,因为那个root[i],还有tx[ ...

  7. 主席树的各类模板(区间第k大数【动,静】,区间不同数的个数,区间=k的个数)...

    取板粗   好东西来的 1.(HDOJ2665)http://acm.hdu.edu.cn/showproblem.php?pid=2665 (POJ2104)http://poj.org/probl ...

  8. HDU 4417 Super Mario(线段树离线处理/主席树)

    Mario is world-famous plumber. His "burly" figure and amazing jumping ability reminded in ...

  9. SPOJ COT Count on a tree(主席树+倍增lca)

    思路:这个题其实就是树上的第k小,主席树的本质还是类似于前缀和一样的结构,所以是完全相同的,所以我们在树上也可以用同样的方法,我们对于每一个节点进行建树,然后和普通的树上相同,ab之间的距离是等于 r ...

最新文章

  1. Hadoop HA 深度解析
  2. python的def函数_Python 学习之 def 函数
  3. 理解JavaScript继承(二)
  4. source insight 常用设置及快捷键
  5. AI知识点(1)--激活函数
  6. Ubuntu 修复windows启动项
  7. (实例篇)php 使用redis锁限制并发访问类示例
  8. C语言二维数组指针(指向二维数组的指针)详解
  9. 微信JSSDK使用签名算法
  10. 战神网络 战神引擎 手游研究院 获取该区补丁失败 如何解决
  11. python2代码转换python3(2018新)
  12. 253:丛林中的路——最小生成树Prim
  13. 余柳:国际视角下城市交通碳中和策略与路径研究
  14. BZOJ1455罗马游戏
  15. CSS—表单的样式设置
  16. pcl聚类----欧式聚类分割方法
  17. 学好英语网html首页制作,网页 英语
  18. 同态加密库Seal库的安装(win11+VS2022)
  19. 【JVM】四、JVM优化-GC调优
  20. java高级面试视频,持续更新~

热门文章

  1. 删除作业计划出错(DELETE语句与 REFERENCE约束FK_subplan_job_id冲突。)
  2. 什么是HTTP Headers?
  3. IDEA+selenium+TestNG+java+git+maven+jenkins实现Web UI自动化集成
  4. 利用Caffe训练模型(solver、deploy、train_val) + python如何使用已训练模型
  5. NotePad++列编辑
  6. 论jquery与vuejs结合时的部分问题
  7. Hibernate学习之hibernate状态
  8. OC中的自动引用计数
  9. 软件开发者的最佳实践
  10. html右键禁用和web页面中添加加入qq群的方式