博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj 2104 K-th Number(主席树,详细有用)
阅读量:5093 次
发布时间:2019-06-13

本文共 5922 字,大约阅读时间需要 19 分钟。

poj 2104 K-th Number(主席树)

主席树就是持久化的线段树,添加的时候,每更新了一个节点的线段树都被保存下来了。
查询区间[L,R]操作的时候,只需要用第R棵树减去第L-1棵树就是区间[L,R]中增加的元素对应的树,然后查询这棵两棵树的差值对应的树就可以达到我们的目的。
每增加一个节点,必然有一条边被改变,那条边上的所有节点都会被改变。除这条边之外的其它节点用的是上一棵树的。
K-th Number
Time Limit: 20000MS   Memory Limit: 65536K
Total Submissions: 62232   Accepted: 21860
Case Time Limit: 2000MS

Description

You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment. 
That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?" 
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.

Input

The first line of the input file contains n --- the size of the array, and m --- the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000). 
The second line contains n different integer numbers not exceeding 10
9 by their absolute values --- the array for which the answers should be given. 
The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).

Output

For each question output the answer to it --- the k-th number in sorted a[i...j] segment.

Sample Input

7 31 5 2 6 3 7 42 5 34 4 11 7 3

Sample Output

563

Hint

This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.

Source

, Northern Subregion

 

 

添加的这个节点离散化之后是1,也就是最左下角的那个节点。

总共是7个数,离散化管它有几个不重复的数,按照最大情况7个个数来算就对了。

所以这7个数是依次会被放到这7个叶子节点上面的来。

数的序列是1 5 2 6 3 7 4

第一个数是1,离散化之后也是1,所以会被放到最左下角3那个位置,所以就是上图右边更新的情况,(注意看节点的下标)。

 

第5棵树根节点的左边有3个,第一棵树根节点左边只有一个,多3-1=2个,但是我要找的是3大的,所以必定在第五棵树减去第一颗树的右边的第一个。

 

 

 

 

测试代码(后面有AC代码)

1 #include 
2 #include
3 #include
4 #include
5 #include
6 using namespace std; 7 const int MAXN = 100010; 8 const int N = MAXN*40; 9 int n,m,q,tot; 10 int T[MAXN],A[MAXN],t[MAXN]; 11 //详单于结构体 12 int lson[N],rson[N],sum[N]; 13 vector
V; 14 int getid(int x) //离散化 15 { 16 return lower_bound(V.begin(),V.end(),x)-V.begin()+1; 17 } 18 int build(int l,int r) //建立一棵空树 19 { 20 int rt = tot++; 21 sum[rt] = 0;//初始化,相当于初始化结构体中的sum元素 22 //不是叶子节点 23 if(l!=r){ 24 int mid=(l+r)>>1; 25 lson[rt] = build(l,mid); 26 rson[rt] = build(mid+1,r); 27 } 28 return rt; 29 } 30 31 32 //比如说第一组数是(0,1),表示继承的第0棵树,然后插入的那个数的id是1 33 int update(int rt,int pos) //把数组中的元素一次加入新的线段树中 34 { 35 int nrt = tot++;//相当于节点13 36 int tmp = nrt; 37 //sum[13]=sum[0]+1,这是插入第一个点的情况,表示sum[13]第一棵树比 sum[0]第0棵树多了一个元素 38 sum[nrt] = sum[rt]+1; 39 int l=1,r=m;//相当于从根节点开始更新 40 while(l
>1; 42 //插入节点在线段树的左边 43 if(pos<=mid) { 44 lson[nrt] = tot++;//左边的节点就是我们新创建的这个节点,相当于节点14 45 rson[nrt] = rson[rt];//右边节点就直接继承前一棵树 ,相当于节点8 46 nrt = lson[nrt];//让13节点向下走到14号节点 47 rt = lson[rt];//前一棵树继续往下走,把前一棵树0号节点的左孩子的值赋值给rt,方便让新的这棵树找得到5号节点,4号节点 48 r = mid;//二分 49 }else { 50 rson[nrt] = tot++; 51 lson[nrt] = lson[rt];//左边直接继承前一棵树 52 nrt = rson[nrt]; 53 rt = rson[rt]; 54 l=mid+1; 55 } 56 sum[nrt] = sum[rt]+1;//节点在前一棵树的基础上面个数+1 57 } 58 return tmp; 59 } 60 61 //第y棵树减第x-1棵树就是xy之间的元素,然后找到第k大的即可 62 //printf("%d\n",V[query(T[x-1],T[y],k)-1]); 63 //相当于是在两棵树的差树的那颗树上面找 64 int query(int lrt,int rrt,int k) 65 { 66 int l=1,r=m;//从根节点开始找 67 while(l
>1; 69 int cnt = sum[lson[rrt]] - sum[lson[lrt]];//找到有多少个数目 70 if(cnt>=k) { 71 r = mid; 72 lrt = lson[lrt]; 73 rrt = lson[rrt]; 74 } else { 75 l = mid+1; 76 k-=cnt;//跑到右边去就要把左边的减掉 77 lrt = rson[lrt];//第一棵树和第五课树都去右孩子,然后是找差值 78 rrt = rson[rrt]; 79 } 80 } 81 return l; 82 } 83 //测试主席树 84 void print(){ 85 cout<<"i"<<" "<<"lson[i]"<<" "<<"rson[i]"<<" "<<"sum[i]"<<" "<

 

 

 

 

 AC代码

1 #include 
2 #include
3 #include
4 #include
5 #include
6 using namespace std; 7 const int MAXN = 100010; 8 const int N = MAXN*40; 9 int n,m,q,tot;10 int T[MAXN],A[MAXN],t[MAXN];11 int lson[N],rson[N],sum[N];12 vector
V;13 int getid(int x) //离散化14 {15 return lower_bound(V.begin(),V.end(),x)-V.begin()+1;16 }17 int build(int l,int r) //建立一棵空树18 {19 int rt = tot++;20 sum[rt] = 0;21 if(l!=r){22 int mid=(l+r)>>1;23 lson[rt] = build(l,mid);24 rson[rt] = build(mid+1,r);25 }26 return rt;27 }28 29 int update(int rt,int pos) //把数组中的元素一次加入新的线段树中30 {31 int nrt = tot++;32 int tmp = nrt;33 sum[nrt] = sum[rt]+1;34 int l=1,r=m;35 while(l
>1;37 if(pos<=mid) {38 lson[nrt] = tot++;39 rson[nrt] = rson[rt];40 nrt = lson[nrt];41 rt = lson[rt];42 r = mid;43 }else {44 rson[nrt] = tot++;45 lson[nrt] = lson[rt];46 nrt = rson[nrt];47 rt = rson[rt];48 l=mid+1;49 }50 sum[nrt] = sum[rt]+1;51 }52 return tmp;53 }54 55 int query(int lrt,int rrt,int k)56 {57 int l=1,r=m;58 while(l
>1;60 int cnt = sum[lson[rrt]] - sum[lson[lrt]];61 if(cnt>=k) {62 r = mid;63 lrt = lson[lrt];64 rrt = lson[rrt];65 } else {66 l = mid+1;67 k-=cnt;68 lrt = rson[lrt];69 rrt = rson[rrt];70 }71 }72 return l;73 }74 int main()75 { //freopen("in.txt","r",stdin);76 scanf("%d%d",&n,&q);tot=0;77 for(int i=1;i<=n;i++) {78 scanf("%d",&A[i]);79 V.push_back(A[i]);80 }81 sort(V.begin(),V.end());82 V.erase(unique(V.begin(),V.end()),V.end());83 m=V.size();84 T[0] = build(1,m);85 for(int i=1;i<=n;i++) {86 T[i] = update(T[i-1],getid(A[i]));87 }88 while(q--) {89 int x,y,k;90 scanf("%d%d%d",&x,&y,&k);91 printf("%d\n",V[query(T[x-1],T[y],k)-1]);92 }93 return 0;94 }

 

转载于:https://www.cnblogs.com/Renyi-Fan/p/8135856.html

你可能感兴趣的文章
正则表达式(进阶篇)
查看>>
无人值守安装linux系统
查看>>
【传道】中国首部淘宝卖家演讲公开课:农业本该如此
查看>>
jQuery应用 代码片段
查看>>
MVC+Servlet+mysql+jsp读取数据库信息
查看>>
黑马程序员——2 注释
查看>>
用OGRE1.74搭建游戏框架(三)--加入人物控制和场景
查看>>
转化课-计算机基础及上网过程
查看>>
android dialog使用自定义布局 设置窗体大小位置
查看>>
ionic2+ 基础
查看>>
互联网模式下我们更加应该“专注”
查看>>
myeclipse集成jdk、tomcat8、maven、svn
查看>>
查询消除重复行
查看>>
Win 10 文件浏览器无法打开
查看>>
[leetcode]Minimum Path Sum
查看>>
内存管理 浅析 内存管理/内存优化技巧
查看>>
【BZOJ 5222】[Lydsy2017省队十连测]怪题
查看>>
Java跟Javac,package与import
查看>>
day-12 python实现简单线性回归和多元线性回归算法
查看>>
Json格式的字符串转换为正常显示的日期格式
查看>>