又是一个线段树的应用,不过跟上一题(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<N<=200000,0<M<5000 )
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<stdio.h> 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(c<t[k].l||c>t[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 ",query(x,y,1)); 74 } 75 } 76 return 0; 77 }