您的位置:首页 > 其它

线段树入门 南阳oj 119

2017-09-13 21:01 183 查看
点击打开链接

士兵杀敌(三)

时间限制:2000 ms  |  内存限制:65535 KB

难度:5
描述
南将军统率着N个士兵,士兵分别编号为1~N,南将军经常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进行比较,计算出两个人的杀敌数差值,用这种方法一方面能鼓舞杀敌数高的人,另一方面也算是批评杀敌数低的人,起到了很好的效果。

所以,南将军经常问军师小工第i号士兵到第j号士兵中,杀敌数最高的人与杀敌数最低的人之间军功差值是多少。

现在,请你写一个程序,帮小工回答南将军每次的询问吧。

注意,南将军可能询问很多次。

输入 只有一组测试数据

第一行是两个整数N,Q,其中N表示士兵的总数。Q表示南将军询问的次数。(1<N<=100000,1<Q<=1000000)

随后的一行有N个整数Vi(0<=Vi<100000000),分别表示每个人的杀敌数。

再之后的Q行,每行有两个正正数m,n,表示南将军询问的是第m号士兵到第n号士兵。输出 对于每次询问,输出第m号士兵到第n号士兵之间所有士兵杀敌数的最大值与最小值的差。
样例输入
5 2
1 2 6 9 3
1 2
2 4

 样例输出

1
7

这题本是RMQ算法模板题,不过用来入门练手线段树也是不错的,用线段树每个节点代表的区间记录两个子节点的最大和最小值,以此递归。

#include<stdio.h>
#define max(x,y) x>y?x:y
#define min(x,y) x<y?x:y
int max,min;
struct node
{
int max,min;
}tree[100000*4];
void build(int k,int L,int R)
{
if(L==R)
{
scanf("%d",&tree[k].max);
tree[k].min=tree[k].max;
return;
}
int mid=(L+R)/2;
build(k*2,L,mid);
build(k*2+1,mid+1,R);
tree[k].max=max(tree[2*k].max,tree[2*k+1].max);//记录该节点所代表区间的最值
tree[k].min=min(tree[2*k].min,tree[2*k+1].min);
}
void search(int k,int L,int R,int qL,int qR)//查找区间最值
{
if(L==qL&&R==qR)
{
max=max(max,tree[k].max);
min=min(min,tree[k].min);
return;
}
int mid=(L+R)/2;
if(mid>=qR)
search(2*k,L,mid,qL,qR);
else if(mid<qL)
search(2*k+1,mid+1,R,qL,qR);
else
{
search(2*k,L,mid,qL,mid);
search(2*k+1,mid+1,R,mid+1,qR);
}
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
build(1,1,n);
while(q--)
{
int L,R;
max=-999999999,min=999999999;
scanf("%d%d",&L,&R);
search(1,1,n,L,R);
printf("%d\n",max-min);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: