题目:http://poj.org/problem?id=3264
题目大意:
给定一个n和m ,输入n,包含n行 代表1~n牛的重量,然后m行,输入p,q,查询在序号为p~q中最大重量的牛和和最小重量的牛之间的差值
题解:
1.首先要注意的是 输入的数据量较大且输入次数较多 因此采用scanf(%d,&a)和printf(%d,&a)进行输入输出 防止超时
2.本题属于区间单点修改和区间查询的题目类型,因此采用线段树做法
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
typedef long long ll;
struct Tree
{
ll l, r;
ll maxx, minn;
ll mid() { return (l + r) / 2; }
}tree[800010];
ll maxv = -10000000;
ll minv = 10000000;
void BuildTree(int root, int l, int r)
{
tree[root].l = l;
tree[root].r = r;
tree[root].maxx = -10000000;
tree[root].minn = 10000000;
//建立左右子树
if (l!= r)
{
BuildTree(root * 2+1, l, (l+r)/2);
BuildTree(root * 2 + 2, (l+r)/2 + 1, r);
}
}
//i为要插入的序号 v为要插入的值 采用二分的方法
void insert(ll root,ll i,ll v)
{
if (tree[root].l==tree[root].r)
{
tree[root].maxx = v;
tree[root].minn = v;
return;
}
tree[root].maxx = max(tree[root].maxx, v);
tree[root].minn = min(tree[root].minn, v);
if (i <= tree[root].mid())
{
insert(2*root+1,i,v);
}
else
{
insert(2 * root + 2, i, v);
}
}
void query(ll root, ll s, ll e)
{
//回溯 满足以下条件 无需再往下进行查找
if (tree[root].maxx <= maxv && tree[root].minn >= minv)
{
return;
}
if (tree[root].l == s && tree[root].r == e)
{
maxv = max(tree[root].maxx, maxv);
minv = min(tree[root].minn, minv);
return;
}
/*
若目标区间只位于左区间 则只查询左子树
第二个同理
否则左右子树均查询
*/
if (e <= tree[root].mid())
{
query(2 * root + 1, s, e);
}
else if (s > tree[root].mid())
{
query(2 * root + 2, s, e);
}
else
{
query(2 * root + 1, s, tree[root].mid());
query(2 * root + 2, tree[root].mid()+1, e);
}
}
int main()
{
ll n, m;
scanf("%lld%lld", &n, &m);
BuildTree(0, 1, n);
for (int i = 0; i < n; i++)
{
ll q;
scanf("%lld", &q);
insert(0, i + 1, q);
}
for (int i = 0; i < m; i++)
{
ll st;
scanf("%lld", &st);
ll en;
scanf("%lld", &en);
minv = 100000000;
maxv = -10000000;
query(0, st, en);
printf("%lld\n", maxv - minv);
}
}