又是一个线段树的应用,不过跟上一题(D-排兵布阵)不同的是,这次是求某段区间上的最值,而不是某段区间和。当然,数据更新是必须的。D题注释已经很详细了,所以这题注释少点。
大致题意:给你N个已经排好的学生成绩,然后有M条指令,输出对应指令的结果。指令有两种:
1.Q i j:询问i到j的最值
2.U i j:把学生编号为i的成绩改为j
输入输出格式:
Sample Input
5 6 //第一行两个整数N,M,表示N个学生和M条指令( 0
1 2 3 4 5 //第二行是N个学生的成绩(对应学生编号)
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 2 9
Q 1 5
Sample Output
5
6
5
9
1 #include
2 #include<string.h>
3
4 int max(int a,int b)//首先定义一个取最大值的函数
5 {
6 return a>b?a:b;
7 }
8
9 struct tree
10 {
11 int l,r,s;
12 };
13
14 char s[5];
15 int m,n,x,y;
16 tree t[600010];//一般存节点的数组是叶子节点的三倍就够了
17
18 void Init(int l,int r,int k)//构造线段树
19 {
20 t[k].l=l;
21 t[k].r=r;
22 if(l==r)//叶子节点
23 {
24 int x;
25 scanf("%d",&x);
26 t[k].s=x;//输入该叶子节点(学生)的分数
27 return ;
28 }
29 int mid=(l+r)/2;
30 Init(l,mid,k*2);//构造左子树
31 Init(mid+1,r,k*2+1);//构造右子树
32 t[k].s=max(t[k*2].s,t[k*2+1].s);//更新父节点数据(取最大值)
33 }
34
35 void updata(int c,int x,int k)//数据的更新操作
36 {
37 if(t[k].l==t[k].r&&t[k].l==c)
38 {
39 t[k].s=x;
40 return ;
41 }
42 if(ct[k].r)
43 return ;
44 updata(c,x,k*2);
45 updata(c,x,k*2+1);
46 t[k].s=max(t[k*2].s,t[k*2+1].s);
47 }
48
49 int query(int l,int r,int k)//数据查询 注意范围落在哪个区间就行了
50 {
51 if(t[k].l==l&&t[k].r==r)
52 return t[k].s;
53 int mid=(t[k].l+t[k].r)/2;
54 if(r<=mid)
55 return query(l,r,k*2);
56 else if(l>=mid+1)
57 return query(l,r,k*2+1);
58 else
59 return max(query(l,mid,k*2),query(mid+1,r,k*2+1));
60 }
61
62 int main()
63 {
64 while(scanf("%d %d",&n,&m)!=EOF)
65 {
66 Init(1,n,1);
67 while(m--)
68 {
69 scanf("%s %d %d",&s,&x,&y);
70 if(s[0]=='U')
71 updata(x,y,1);
72 else
73 printf("%d\n",query(x,y,1));
74 }
75 }
76 return 0;
77 }
View Code