ACM——I Hate It(线段树的进化版)

Description

很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。
这让很多学生很反感。

不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。

Input

本题目包含多组测试,请处理到文件结束。
在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。
学生ID编号分别从1编到N。
第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。
接下来有M行。每一行有一个字符 C (只取'Q'或'U') ,和两个正整数A,B。
当C为'Q'的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。
当C为'U'的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。

Output

对于每一次询问操作,在一行里面输出最高成绩。

Sample Input

	
5 6
		1 2 3 4 5
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 2 9
Q 1 5

Sample Output

	5
6
5
9

 

Hint

Huge input,the C function scanf() will work better than cin


解释:这题主要意思难点在如何花较少时间去取得一段学生的最高成绩如何更新某个学生的成绩。所以此题,有以下思路:

1.在构建每个线段树的时候,除了最下面的一排,每一个支点都储存下面左孩子和右孩子的最大值(不是和),这样的话读取某段学生
成绩最大值就会快很多。

2.因为每次跟新某位学生成绩时,上面的支点肯定也要做相应改变,所以用到了递归思想从下到上更新
成绩。

下面是代码:
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #define max(a,b) (a > b ? a : b)
 5 #define min(a,b) (a > b ? b : a)
 6 
 7 using namespace std;
 8 
 9 const int MAXN=200010;
10 
11 struct student
12 {
13     int left,right;
14     int nSum;
15 }segTree[MAXN*3];
16 int num[MAXN];
17 
18 
19 
20 
21 void Build(int i,int left,int right)//递归算法,构建一颗线段树
22 {
23     segTree[i].left=left;
24     segTree[i].right=right;
25     if(left==right)
26     {
27         segTree[i].nSum=num[left];
28         return;
29     }
30     int mid=(left+right)>>1;//除2
31     Build(i<<1,left,mid);//i*2 a
32     Build(i<<1|1,mid+1,right);//i*2+1 b
33     segTree[i].nSum=(segTree[i<<1].nSum>segTree[i<<1|1].nSum?segTree[i<<1].nSum:segTree[i<<1|1].nSum);  //取最大值
34 }
35 
36 
37 void U(int i,int tleft,int b)//更新成绩
38 {
39     
40     if(segTree[i].left==tleft&&segTree[i].right==tleft)
41     {
42         segTree[i].nSum=b;
43         return;
44     }
45     int mid=(segTree[i].left+segTree[i].right)>>1;
46 
47     if(tleft<=mid)
48         U(i<<1,tleft,b);
49     else
50         U(i<<1|1,tleft,b);
51 
52     segTree[i].nSum=(segTree[i].nSum>b?segTree[i].nSum:b);
53 
54 }
55 
56 
57 int Q(int i,int left,int right)
58 {
59     if(segTree[i].left==left&&segTree[i].right==right)
60     {
61         return segTree[i].nSum;
62     }
63     int middle=(segTree[i].left+segTree[i].right)>>1;
64     if(left>middle)
65     {
66         return Q(i<<1|1,left,right);
67     }
68     else if(right<=middle)
69     {
70         return Q(i<<1,left,right);
71     }
72     else
73     {
74         int a=Q(i<<1,left,middle);
75         int b=Q(i<<1|1,middle+1,right);
76         return a>b?a:b;
77     }
78 }
79 
80 
81 int main()
82 {
83     int n,t,x,y;
84     char C;
85     while(scanf("%d%d",&n,&t)!=EOF){
86         for(int i=1; i<= n; i++)scanf("%d",&num[i]);
87         Build(1,1,n);
88         while(t--){
89             getchar();   //吸收掉多余的换行键
90             scanf("%c%d%d",&C,&x,&y);
91 
92             if(C == 'U')
93                 U(1,x,y);
94             else 
95                 printf("%d\n",Q(1,x,y));    
96         }    
97     }    
98     return 0;
99 }



原文地址:https://www.cnblogs.com/shadervio/p/5696908.html