码迷,mamicode.com
首页 > 其他好文 > 详细

并不对劲的st表

时间:2018-01-30 12:43:59      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:个数   次方   ima   main   i++   部分   img   struct   height   

对于带修改的区间求和能做到O(n log n)预处理,O(log n)查询;而不带修改的可以做到O(n)预处理,O(1)查询。那么不带修改的区间最值能做到O(1)查询吗?

区间最值有这样一个性质:对于一段区间的两个子区间,如果它们覆盖了整个区间(可以有重叠部分),那么这两段区间各自的最大(或最小)值的最大(或最小)值就等于整个区间的最大(或最小)值。

这样的话,可以倍增地求出从每个位置开始的2的x次方的区间最值,预处理每个数的log。查询l-r这一段区间时按如图所示的方式合并就行了。

 技术分享图片

 

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define maxn 100010 
using namespace std;
int read()
{
	int f=1,x=0;char ch=getchar();
	while(isdigit(ch)==0 && ch!=‘-‘)ch=getchar();
	if(ch==‘-‘)f=-1,ch=getchar();
	while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
	return x*f;
}
void write(int x)
{
	int ff=0;char ch[15];
	if(x<0)
	{
		x=-x;
		putchar(‘-‘);
	}
	while(x)ch[++ff]=(x%10)+‘0‘,x/=10;
	if(ff==0)putchar(‘0‘);
	while(ff)putchar(ch[ff--]);
	putchar(‘\n‘);
}
struct ST
{
	int st[maxn][20],logx[maxn],two[maxn];
	int n,q,l,r;
	void ask()
	{
		l=read(),r=read();
		write(max(st[l][logx[r-l+1]],st[r-two[r-l+1]+1][logx[r-l+1]]));
	}
	void work()
	{
		n=read(),q=read();
		for(int i=1,j=1,k=0;i<=n;i++)
	    {
	    	st[i][0]=read();
			if((j<<1)<=i)j<<=1,k++;
			logx[i]=k;
			two[i]=j;
		} 
		for(int i=1;(1<<i)<=n;i++)
		{
			for(int j=1;j+(1<<(i))-1<=n;j++)
			{
				st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]);
			//	cout<<st[j][i]<<" "; 
			}//cout<<endl;
		}
		while(q--)
		{
			ask();
		}
	}//1 2 3 4 5
}t;
int main()
{
	t.work();
	return 0;
}/*
8 8
9 3 1 7 5 6 0 8
1 6
1 5
2 7
2 6
1 8
4 8
3 7
1 8
*/

  

并不对劲的st表

标签:个数   次方   ima   main   i++   部分   img   struct   height   

原文地址:https://www.cnblogs.com/xzyf/p/8383480.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!