// 2404K 3688MS G++
#include <stdio.h>
#include <string.h>
const int MAX = 50010;
struct TreeNode {
int left;
int right;
int Max;
int Min;
};
typedef struct TreeNode TreeNode;
TreeNode tree[MAX<<2];
#define INF 9999999
void buildTree(int pos, int left, int right) {
TreeNode & curNode = tree[pos];
curNode.left = left;
curNode.right = right;
curNode.Max = -INF;
curNode.Min = INF;
if (left == right) {
return;
} else {
int mid = (left + right)>>1;
buildTree(pos<<1, left, mid);
buildTree(pos<<1|1, mid+1, right);
}
}
void pushUp(int pos) {
if (pos == 1) {
return;
} else {
int parentPos = pos>>1;
TreeNode & parentNode = tree[parentPos];
TreeNode & leftNode = tree[parentPos<<1];
TreeNode & rightNode = tree[parentPos<<1|1];
int childMax = leftNode.Max > rightNode.Max ? leftNode.Max: rightNode.Max;
int childMin = leftNode.Min < rightNode.Min ? leftNode.Min: rightNode.Min;
char continuePushUp = 0;
int parentMax = parentNode.Max;
int parentMin = parentNode.Min;
if (parentMax < childMax) {
continuePushUp = 1;
parentNode.Max = childMax;
}
if (parentMin > childMin) {
continuePushUp = 1;
parentNode.Min = childMin;
}
// if (continuePushUp) {
// pushUp(parentPos);
// }
}
}
void updateSingleCow(int pos, int cowId, int cowHeight) {
TreeNode & curNode = tree[pos];
int curLeft = curNode.left;
int curRight = curNode.right;
if (curLeft == curRight && curLeft == cowId) {
curNode.Max = cowHeight;
curNode.Min = cowHeight;
} else {
int mid = (curLeft + curRight)>>1;
if (cowId <= mid) {
updateSingleCow(pos<<1, cowId, cowHeight);
} else {
updateSingleCow(pos<<1|1, cowId, cowHeight);
}
}
pushUp(pos);
}
void query(int pos, int rangeLeft, int rangeRight, int & max, int & min) {
TreeNode & curNode = tree[pos];
int curLeft = curNode.left;
int curRight = curNode.right;
if (curLeft == rangeLeft && curRight == rangeRight) {
max = curNode.Max;
min = curNode.Min;
} else {
int mid = (curLeft + curRight)>>1;
if (rangeRight <= mid) {
query(pos<<1, rangeLeft, rangeRight, max, min);
} else if (rangeLeft <= mid && rangeRight > mid) {
int max1;
int max2;
int min1;
int min2;
query(pos<<1, rangeLeft, mid, max1, min1);
query(pos<<1|1, mid+1, rangeRight, max2, min2);
max = max1 > max2 ? max1: max2;
min = min1 < min2 ? min1: min2;
} else if (rangeLeft > mid) {
query(pos<<1|1, rangeLeft, rangeRight, max, min);
}
}
}
int cowNum;
int queryNum;
int main() {
while (scanf("%d %d", &cowNum, &queryNum) != EOF) {
buildTree(1, 1, cowNum);
for (int i = 1; i <= cowNum; i++) {
int cowHeight;
scanf("%d", &cowHeight);
updateSingleCow(1, i, cowHeight);
}
int rangeBegin;
int rangeEnd;
for (int i = 1; i <= queryNum; i++) {
int max;
int min;
scanf("%d %d", &rangeBegin, &rangeEnd);
query(1, rangeBegin, rangeEnd, max, min);
printf("%d\n", max - min);
}
}
}
险过... 果然这道题用线段树做不是最优,应该有专门的RMQ算法,只是手痒,用线段树搞了一把,
WA了一次,因为给的INF一开始是99999,而题目正常值最大能到100000 ......
从线段树角度看,是到很简单的题,每个节点保存当前区间的最大和最小值即可,查询时根据区间分布情况,递归或者直接比较即可。
这道题其实没有最充分的利用线段树的优点: 可以适应动态变化(一开始初始化cow的高度也算是种动态变化吧) 以及 延迟标记, 毕竟不是为线段树而生的题.