hunnu11460—区间求最值(线段树模板)

题目链接:传送门

区间求最值
Time Limit: 3000ms, Special Time Limit:7500ms, Memory Limit:32768KB
Total submit users: 83, Accepted users: 60
Problem 11460 : No special judgement
Problem description
  给定一个长度为N 的数组,有q个询问,每个询问是求在数组的一段区间内那个元素的因子的个数最大,比如24的因子的个数就是8。 
Input
  首先是一个整数t,表示有t组测试数据,每组测试数据的第一行是一个整数N(1<=N<=10^6),第二行有N个整数ai(1<=ai<=10^6,i=1,2,.....N)表示数组的元素。第三行有一个整数q(1<=q<=10^5),代表有q个询问,接下来每一行有两个整数,li,ri(li<=ri,li>=1,ri<=N).代表数组的一段区间,并且li+1>=li,ri+1>=ri
Output
  对于每组数据的每个询问都输出一个整数表示在这段区间里面元素因子个数的最大值。
Sample Input
1
10
2 3 5 6 9 11 12 36 39 44
3
2 6
3 8
3 9
Sample Output
4
9
9

解题思路:先打表求出1000000以内每个数的因子个数,然后线段树求区间最大值,用RMQ会爆内存


#include   
#include   
#include   
#include   
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;  
typedef __int64  ll;
const int N = 1000008;
const int M = 5007;
const int INF = 0x3fffffff;
const int mod = 1e9+7;
const double Pi = acos(-1.0);
const double sm = 1e-9;

int rec[N<<2];//Sum求和,Add为懒惰标记   
int A[N];//存原数组数据下标[1,n] 

//PushUp函数更新节点信息 ,这里是求和  
void PushUp(int rt){rec[rt]=max(rec[rt<<1],rec[rt<<1|1]);}  
//Build函数建树   
void Build(int l,int r,int rt){ //l,r表示当前节点区间,rt表示当前节点编号  
	if(l==r) {//若到达叶节点   
		rec[rt]=A[l];//储存数组值   
		return;  
	}  
	int m=(l+r)>>1;  
	//左右递归   
	Build(l,m,rt<<1);  
	Build(m+1,r,rt<<1|1);  
	//更新信息   
	PushUp(rt);  
}  

int Query(int L,int R,int l,int r,int rt){//L,R表示操作区间,l,r表示当前节点区间,rt表示当前节点编号  
	if(L <= l && r <= R){  
		//在区间内,直接返回   
		return rec[rt];  
	}  
	int m=(l+r)>>1;  

	//累计答案  
	int ANS=0;  
	if(L <= m) ANS=max(ANS,Query(L,R,l,m,rt<<1));  
	if(R >  m) ANS=max(ANS,Query(L,R,m+1,r,rt<<1|1));  
	return ANS;  
}   

int num[N];
void getNumDivisor( int n )
{

	fill( num , num+N , 0 );
	for( int i = 1 ; i*i < n ; ++i ){
		for( int j = i ; i*j < n ; ++j ){
			num[i*j] += 2;
			if( i == j ) num[i*j]--;
		}
	}
}

int main()
{
	getNumDivisor(N);
	int T,n,m,a,b;
	scanf("%d",&T);
	while( T-- ){
		scanf("%d",&n);
		for( int i = 1 ; i <= n ; ++i ){
			scanf("%d",&a);
			A[i] = num[a];
		}
		Build(1,n,1);
		scanf("%d",&m);
		for( int i = 0 ; i < m ; ++i ){
			scanf("%d%d",&a,&b);
			printf("%d\n",Query(a,b,1,n,1));
		}
	}
	return 0;
}


你可能感兴趣的:(数据结构---线段树)