士兵杀敌简单线段树

Posted C-DmLy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了士兵杀敌简单线段树相关的知识,希望对你有一定的参考价值。

题目描述

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

来源

 

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

 

题解:

  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 }

 

以上是关于士兵杀敌简单线段树的主要内容,如果未能解决你的问题,请参考以下文章

nyoj-119 士兵杀敌 线段树

NYOJ116 士兵杀敌线段树

nyoj 119 士兵杀敌 线段树单点更新

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

南阳116----士兵杀敌

nyoj 123 士兵杀敌树状数组+插线问点