nyoj 1185 最大最小值

最大最小值

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 2
描述
给出N个整数,执行M次询问。
对于每次询问,首先输入三个整数C、L、R:

    如果C等于1,输出第L个数到第R个数之间的最小值;

    如果C等于2,输出第L个数到第R个数之间的最大值;

    如果C等于3,输出第L个数到第R个数之间的最小值与最大值的和。

(包括第L个数和第R个数)。

输入
首先输入一个整数T(T≤100),表示有T组数据。
对于每组数据,先输入一个整数N(1≤N≤10000),表示有N个整数;
接下来一行有N个整数a(1≤a≤10000);
然后输入一个整数M,表示有M次询问;
接下来有M行(1≤M≤10000),每行有3个整数C、L、R(1≤C≤3,1≤L≤R≤N)。
输出
按照题意描述输出。每个输出占一行。
样例输入
2
4
1 3 2 4
2
1 1 4
2 2 3
5
1 2 3 4 5
1
3 1 5
样例输出
1
3
6

这道题目用st算法或者线段树就能解决,一个简单的题,只要看懂线段树与st算法就能解决。

#include <cstdio>
#include <algorithm>
#include <cmath>
//#define scanf scanf_s
using namespace std;
struct cd {
	int min;
	int max;
};
#define max_n 10005
cd sa[max_n][30];
int n;
void set()
{
	int i, j;
	for (j = 1; (1 << j) <= n; j++)
	{
		for (i = 0; i + (1 << j) - 1 < n; i++)
		{
			sa[i][j].max = max(sa[i][j - 1].max, sa[i + (1 << (j - 1))][j - 1].max);
			sa[i][j].min = min(sa[i][j - 1].min, sa[i + (1 << (j - 1))][j - 1].min);
			//cout << sa[i][j].min << " ";
		}
		//cout << endl;
	}
}
int get(int a, int b, int c)
{
	int j = (int)log2(c-b+1);
	int s = max(sa[b][j].max, sa[c - (1 << j) + 1][j].max);
	int k = min(sa[b][j].min, sa[c - (1 << j) + 1][j].min);
	if (a == 1)
		return k;
	else if (a == 2)
		return s;
	else
		return s + k;
}
int main()
{
	int i;
	scanf("%d",&i);
	while (i--)
	{
		int a;
		int b, c, d, s;
		scanf("%d",&n);
		for (a = 0; a < n; a++)
		{
			scanf("%d",&sa[a][0].min);
			sa[a][0].max = sa[a][0].min;
		}
		set();
		scanf("%d",&s);
		while (s--)
		{
			scanf("%d%d%d",&b,&c,&d);
			printf("%d\n",get(b,c-1,d-1));
		}
	}
}


你可能感兴趣的:(线段树,nyoj,ST算法)