hdu2665 主席树模板题
2016-02-02 02:22
274 查看
题目
http://acm.hdu.edu.cn/showproblem.php?pid=2665
区间k大值,区间极值很容易想到线段树,如果k是个位数的话,可以考虑开k个域的线段树= =,,,,滚~
又称可持久化线段树,函数式线段树
也许是上面两个字看的太长,同时主席两字给人一种不明觉厉的感觉,,,so,嘿嘿嘿
关于主席树的讲解可以看这
http://wenku.baidu.com/link?url=6sjYgDa2UEZujFwLE4KDqgJlOs0tio-hwKMoDBexBLKT6DSgSiq4Ed-w8cHF4L3JraAflBURPdzeHeOft-f02RT1xfneYIfM5pTVs3t1cBi
先离散化,对每个点i,建一个1~i的线段树(大小是数字的个数)
记录该前缀序列里出现的值的次数;记离散后的标记为1~n;
对于区间[x,y]的第k大的值,那么从root[x-1],root[y]开始,
t=root[y].[1,mid]-root[x-1].[1,mid] ,t表示区间[x,y]内值在[1,mid]的个数
先判断t是否大于K,如果t大于k,那么说明在区间[x,y]内存在[1,mid]的数的个数大于k,
也就是第k大的值在[1,mid]中,否则在[mid+1,r]中;
这样我们依次同时从root[x-1],root[y]往下走
当l==r时 第k大的值就是离散后标记为l的值;
如果每棵线段都建完整的化,n^2肯定会mle,,,BANG!!!
我们发现对于前缀[1,i]和前缀[1,i+1]的线段树,如果b[i+1]<=mid (b[i+1]表示a[i+1]离散后的标记)
那么线段树i和线段树i+1的左边是完全相同的,根本不需要在建,直接链过去就好;
那么对于一棵新的线段树其实我们最多要建的节点数为log(n);nlog(n)的节点数,duangduangduang
存个代码吧,,,,以后如果写熟练了有空写个去重的离散
http://acm.hdu.edu.cn/showproblem.php?pid=2665
区间k大值,区间极值很容易想到线段树,如果k是个位数的话,可以考虑开k个域的线段树= =,,,,滚~
又称可持久化线段树,函数式线段树
也许是上面两个字看的太长,同时主席两字给人一种不明觉厉的感觉,,,so,嘿嘿嘿
关于主席树的讲解可以看这
http://wenku.baidu.com/link?url=6sjYgDa2UEZujFwLE4KDqgJlOs0tio-hwKMoDBexBLKT6DSgSiq4Ed-w8cHF4L3JraAflBURPdzeHeOft-f02RT1xfneYIfM5pTVs3t1cBi
先离散化,对每个点i,建一个1~i的线段树(大小是数字的个数)
记录该前缀序列里出现的值的次数;记离散后的标记为1~n;
对于区间[x,y]的第k大的值,那么从root[x-1],root[y]开始,
t=root[y].[1,mid]-root[x-1].[1,mid] ,t表示区间[x,y]内值在[1,mid]的个数
先判断t是否大于K,如果t大于k,那么说明在区间[x,y]内存在[1,mid]的数的个数大于k,
也就是第k大的值在[1,mid]中,否则在[mid+1,r]中;
这样我们依次同时从root[x-1],root[y]往下走
当l==r时 第k大的值就是离散后标记为l的值;
如果每棵线段都建完整的化,n^2肯定会mle,,,BANG!!!
我们发现对于前缀[1,i]和前缀[1,i+1]的线段树,如果b[i+1]<=mid (b[i+1]表示a[i+1]离散后的标记)
那么线段树i和线段树i+1的左边是完全相同的,根本不需要在建,直接链过去就好;
那么对于一棵新的线段树其实我们最多要建的节点数为log(n);nlog(n)的节点数,duangduangduang
存个代码吧,,,,以后如果写熟练了有空写个去重的离散
[code]//嘿嘿嘿 # include <cstdio> # include <iostream> # include <algorithm> # define N 100100 using namespace std; int i,n,m,root ,a ,p ,b ,cnt; struct node{int lc,rc,w;}T[N*30]; bool cmp(int i,int j){return a[i]<a[j];} void build(int &rot,int l,int r,int x){ T[++cnt]=T[rot];rot=cnt; T[cnt].w++; if (l==r)return ; int mid=(l+r) >> 1; if (x<=mid)build(T[cnt].lc,l,mid,x); else build(T[cnt].rc,mid+1,r,x); } int query(int x,int y,int l,int r,int k){ if (l==r)return l; int t=T[T[y].lc].w-T[T[x].lc].w; int mid=(l+r) >> 1; if (t>=k)return query(T[x].lc,T[y].lc,l,mid,k); else return query(T[x].rc,T[y].rc,mid+1,r,k-t); } int main(){ //freopen("fuck.in","r",stdin); int cas;scanf("%d",&cas); for (;cas--;){ root[0]=0;cnt=0; scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) {scanf("%d",&a[i]);p[i]=i;} sort(p+1,p+n+1,cmp); for (int i=1;i<=n;i++)b[p[i]]=i; for (int i=1;i<=n;i++){ root[i]=root[i-1]; build(root[i],1,n,b[i]); } for (int i=1;i<=m;i++){ int x,y,k; scanf("%d%d%d",&x,&y,&k); int t=query(root[x-1],root[y],1,n,k); printf("%d\n",a[p[t]]); } } return 0; }
相关文章推荐
- MSP430WARE++的使用4:GPIO的使用方法a
- 应用jQuery插件pagination进行分页处理
- 设计模式之命令模式
- hdu 1279 验证角谷猜想(简单的模拟)
- 最近5年133个Java面试问题列表
- 基础知识篇(2)
- SSH连接出错问题收集
- install composer on ubuntu14.04
- how to install qt on ubuntu
- 改革后解放军领导管理体系全揭秘
- C#自定义控件 ————进度条
- Codeforces 621A Wet Shark and Odd and Even
- 设计模式之迭代器模式
- A Simple Problem with Integers (POJ_3468) 线段树+区间更新
- 给久坐族的10个保健建议
- MSP430应用技巧3:MSP-FET430UIF V3驱动程序的安装
- JPA 不在 persistence.xml 文件中配置每个Entity实体类的2种解决办法
- pairing heap 学习以及对于dijkstra算法的再分析
- Codeforces Round #238 (Div. 2) 总结
- POJ 2892解题报告