区间最值查询.docxVIP

  1. 1、本文档共24页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
区间最值查询

RMQ算法RMQ算法全称为(Range Minimum/Maximum Query),即区间最值查询,解决这种问题有两种比较高效的方法:分别为ST算法以及线段树。它们两者都要进行一定的预处理。【ST算法】预处理的核心思想是动态规划,通过把每一个点开始的一段区间不断一分为二,直至最后一段的长度为1,然后再一步一步返回回去。代码:int Log( int N) {return log((double)(N))/log(2.0);}void Table() {for( int i=1; i=N; i++) F[i][0]=a[i]; int n= Log(N); for( int j=1; j=n; j++) for( int i=1; i=N; i++)if( i +(1(j-1) )= N)F[i][j]=max( F[i][j-1], F[i+(1(j-1))][j-1]); }若输入:3 2 4 5 6 8 1 2 9 7若序列生成ST表如下:上述代码是求区间最大值的算法,求最小值只需要稍作修改即可。但要注意,为了节省空间,我们按以下规律存储:F[i][j]表示的既是从第i个点开始,到第(i+(1j)-1)个点的最值。然后便可以按照上述思想推出转移方程:F[i][j]=Max( F[i][j-1], F[i+(1(j-1))][j-1]);在这里需要注意一下循环顺序,外面那一层是for(j),里层for(i)。在这里需要调用cmath库一个函数log,我们若想求得N=2k中的k,就可以用程序中的公式: int k=(int)(log((double)(N))/log(2.0))。到了查询的时候,就只要按照存储规律提取就可以了,将目标区间分成两段,并将其最值求出即可:int RMQ( int nStart, int nEnd) { int nLog =Log(nEnd-nStart+1); return max( F[nStart][nLog], F[nEnd-(1 nLog)+1][nLog] ); }该算法的时间复杂度为O(NlogN)【线段树】(建造线段树)和胜者树类似,线段树的空间需求也是4*N。用递归构建胜者树:void build(int node, int begin, int end) { if (begin==end) segTree[node] =array[begin]; else { build(2*node, begin, (begin+end)/2); build(2*node+1, (begin+end)/2+1, end); segTree[node]=max(segTree[2 *node], segTree[2 *node+1]); }}查询与RMQ原理相似,程序如下:long long query( int x, int l, int r){ if( tree[x].l =l tree[x].r =r) return tree[x].sum; if( tree[x].l r || tree[x].r l) return 0; return query( x*2, l, r)+query( x*2+1, l, r);}1247逆序对[题目描述]给定一个数组A,它包含N个整数,分别是A[1],A[2],...A[N]。如果存在下标i和j,使得 i j 且 A[i]>A[j]同时成立,则(i,j)就为一个“逆序对”。那么A数组总共有多少对不同的“逆序对”?范围第一行为n(1≤n≤100000)。接下来是n行,每行一个长整型范围内的整数。分析此题需要用到离散化、数组计数,需要用线段树进行维护每个区间对应数值出现的数目。不断加入数,然后在线段树中快速查询每一段的和,加起来即可。下面贴上代码:#include cstdio#include algorithm#include cstring#include cmath#include iostreamusing namespace std;const int ML=100021;struct node{ int l,r;long long sum;}tree[4*ML];struct lsh {int num, p;}a[ML];bool _sort(lsh x, lsh y) {return x.numy.num;}int n, m;long long pm1[ML],pm2[ML];void buildTree(int x,int l,int r){ tree[x].l=l, tre

文档评论(0)

xcs88858 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

版权声明书
用户编号:8130065136000003

1亿VIP精品文档

相关文档