士兵杀敌(三)简单线段树

题目描述

南将军统率着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

来源

NYOJ

小学弟说不会,自己就写了一发,半年没写线段树了啊....写的好搓...别看了...

题解:

  1 #include <vector>
  2 #include <map>
  3 #include <set>
  4 #include <algorithm>
  5 #include <iostream>
  6 #include <cstdio>
  7 #include <cmath>
  8 #include <cstdlib>
  9 #include <string>
 10 #include <cstring>
 11 #include <queue>
 12 using namespace std;
 13
 14 const int maxn = 100010 , INF = -214748364 , INFF = 0x3f3f3f3f;
 15 int a[maxn], b[4*maxn], c[4*maxn] , A, B;
 16
 17 void update(int o, int L, int R)
 18 {
 19     if(L == R)
 20         b[o] = B;
 21     else
 22     {
 23         int M = L + (R - L) / 2;
 24         if(A <= M)
 25             update(2*o, L, M);
 26         else
 27             update(2*o+1, M+1, R);
 28         b[o] = max(b[2*o], b[2*o+1]);
 29     }
 30 }
 31
 32 int query(int o, int L, int R)
 33 {
 34     if(A <= L && R <= B)
 35        return c[o];
 36     int M = L + (R - L) / 2, ans = INF;
 37     if(A <= M)
 38         ans = max(ans, query(2*o, L, M));
 39     if(B > M)
 40         ans = max(ans, query(2*o+1, M+1, R));
 41     return ans;
 42 }
 43
 44 int qquery(int o, int L, int R)
 45 {
 46     if(A <= L && R <= B)
 47        return b[o];
 48     int M = L + (R - L) / 2, ans = INFF;
 49     if(A <= M)
 50         ans = min(ans, qquery(2*o, L, M));
 51     if(B > M)
 52         ans = min(ans, qquery(2*o+1, M+1, R));
 53     return ans;
 54 }
 55
 56 void build(int o, int L, int R)
 57 {
 58
 59     if(L == R)
 60     {
 61         b[o] = a[L];
 62         return;
 63     }
 64     int M = L + (R - L) / 2;
 65     if(L <= M)
 66         build(2*o, L, M);
 67     if(R > M)
 68         build(2*o+1, M+1, R);
 69     b[o]=min(b[2*o], b[2*o+1]);
 70
 71 }
 72
 73 void build1(int o, int L, int R)
 74 {
 75
 76     if(L == R)
 77     {
 78         c[o] = a[L];
 79         return;
 80     }
 81     int M = L + (R - L) / 2;
 82     if(L <= M)
 83         build1(2*o, L, M);
 84     if(R > M)
 85         build1(2*o+1, M+1, R);
 86     c[o]=max(c[2*o], c[2*o+1]);
 87
 88 }
 89
 90 int main()
 91 {
 92     int N, M;
 93     while(~scanf("%d%d\n", &N, &M))
 94     {
 95         b[0]=INFF;
 96         for(int i = 1; i <= N; i++) scanf("%d", &a[i]);
 97         build(1, 1, N);
 98         build1(1, 1, N);
 99         while(M--)
100         {
101             scanf("%d%d", &A, &B);
102
103             int minn= qquery(1, 1, N);
104
105             int maxx= query(1, 1, N);
106             printf("%d\n",maxx-minn);
107         }
108     }
109     return 0;
110 }
时间: 2024-12-21 11:02:46

士兵杀敌(三)简单线段树的相关文章

简单线段树

一.单点更新 hdu1166区间和 #include <iostream> #include <algorithm> #include <cmath> using namespace std; const int maxn=50005; const int maxnnode=1<<19; struct node{ int value; int left,right; }node[maxnnode]; int father[maxn]; void BuidTr

【简单线段树】I Hate It (求范围内最大)

I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 53477    Accepted Submission(s): 21005 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感.不管你喜不喜欢,现在需要你做的是,就是按照老师的

poj 3468(简单线段树区间更新)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 61936   Accepted: 18934 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

nyoj 119士兵杀敌(三)(线段树区间最值查询,RMQ算法)

题目119 题目信息 执行结果 本题排行 讨论区 士兵杀敌(三) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描写叙述 南将军统率着N个士兵,士兵分别编号为1~N,南将军常常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进行比較,计算出两个人的杀敌数差值.用这样的方法一方面能鼓励杀敌数高的人,还有一方面也算是批评杀敌数低的人,起到了非常好的效果. 所以,南将军常常问军师小工第i号士兵到第j号士兵中,杀敌数最高的人与杀敌数最低的人之间军功差值是多少. 如今,请你写一个程

nyoj-119 士兵杀敌(三) 线段树

士兵杀敌(三) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 南将军统率着N个士兵,士兵分别编号为1~N,南将军经常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进行比较,计算出两个人的杀敌数差值,用这种方法一方面能鼓舞杀敌数高的人,另一方面也算是批评杀敌数低的人,起到了很好的效果. 所以,南将军经常问军师小工第i号士兵到第j号士兵中,杀敌数最高的人与杀敌数最低的人之间军功差值是多少. 现在,请你写一个程序,帮小工回答南将军每次的询问吧. 注意,南将军可能询问很多

士兵杀敌(四)(树状数组+线段树)

士兵杀敌(四) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 南将军麾下有百万精兵,现已知共有M个士兵,编号为1~M,每次有任务的时候,总会有一批编号连在一起人请战(编号相近的人经常在一块,相互之间比较熟悉),最终他们获得的军功,也将会平分到每个人身上,这样,有时候,计算他们中的哪一个人到底有多少军功就是一个比较困难的事情,军师小工的任务就是在南将军询问他某个人的军功的时候,快速的报出此人的军功,请你编写一个程序来帮助小工吧. 假设起始时所有人的军功都是0. 输入

NYOJ 119 士兵杀敌(三)

士兵杀敌(三) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 南将军统率着N个士兵,士兵分别编号为1~N,南将军经常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进行比较,计算出两个人的杀敌数差值,用这种方法一方面能鼓舞杀敌数高的人,另一方面也算是批评杀敌数低的人,起到了很好的效果. 所以,南将军经常问军师小工第i号士兵到第j号士兵中,杀敌数最高的人与杀敌数最低的人之间军功差值是多少. 现在,请你写一个程序,帮小工回答南将军每次的询问吧. 注意,南将军可能询问很多

[Noi2016十连测第三场]线段树

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 #define maxn 100005 8 #define maxk 4000005 9 int n,m,q,tot,t1,t2,ans,L[maxn][18],R[maxn][18]; 1

HDOJ-1754(简单线段树)

最近开始重新学习线段树,先从最简单的开始吧! I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 46762    Accepted Submission(s): 18316 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 不管