HDU-1754-I Hate It-线段树-求区间最值和单点修改
开学新拉的题目,老题重做,思路会稍微比之前清晰,不过这也算是一点点进步了。
很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。 这让很多学生很反感。 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。 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
题意:
Q a-b 成绩最高的学生 每一次询问输出成绩
U a、b 把a学生的成绩改为b分
思路:
求区间最值和单点修改
单点修改不需要懒惰标记,因为每次都是访问到底层(最后一个叶节点)
小细节:
|:有1则1
<<1 :等同于*2
i<<1|1:等同于i*2+1
a[4*N]:数组需要开到四倍空间
1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<string.h> 5 #include<cmath> 6 #include<queue> 7 #include<stdlib.h> 8 typedef long long ll; 9 using namespace std; 10 const int N=200020; 11 12 //5 6 13 //1 2 3 4 5 14 //Q 1 5 ->5 15 //U 3 6 16 //Q 3 4 ->6 17 //Q 4 5 ->5 18 //U 2 9 19 //Q 1 5 ->9 20 21 int a[4*N];//需要开到四倍空间 22 23 24 //每个父节点记录的是它下面的两个节点的最大值 25 void build(int L,int R,int i) 26 { 27 if(L==R) 28 { 29 scanf("%d",&a[i]); 30 return; 31 } 32 int mid=(L+R)>>1; 33 build(L,mid,i<<1); 34 build(mid+1,R,i<<1|1); 35 a[i]=max(a[i<<1],a[i<<1|1]);//pushup(i)////每次传的时候把根节点也往下去寻找最大值 36 ////比较其左右两个节点的大小,取最大值 37 //看题目给的需要求什么 38 } 39 40 //update(aa,bb,1,n,1) 41 //把下标为aa的元素修改成bb,更新节点值,更改节点 42 void update(int aa,int bb,int L,int R,int i) 43 { 44 if(L==R) 45 { 46 a[i]=bb; 47 return; 48 } 49 int mid=(L+R)>>1; 50 if(aa<=mid)//不是L<=mid 51 update(aa,bb,L,mid,i<<1); 52 else 53 update(aa,bb,mid+1,R,i<<1|1); 54 a[i]=max(a[i<<1],a[i<<1|1]); 55 } 56 57 //query(aa,bb,1,n,1) 58 int query(int left,int right,int L,int R,int i) 59 { 60 if(left<=L&&right>=R) 61 return a[i]; 62 int mid=(L+R)>>1; 63 int ans=-1; 64 if(left<=mid) 65 ans=max(ans,query(left,right,L,mid,i<<1)); 66 // else 67 if(right>mid) 68 ans=max(ans,query(left,right,mid+1,R,i<<1|1)); 69 return ans; 70 } 71 72 int main() 73 { 74 int n,m; 75 while(~scanf("%d %d",&n,&m)) 76 { 77 memset(a,0,sizeof(a)); 78 build(1,n,1);//传入最左端点,最右端点,根节点进行建树 79 //建树的过程中输入每一个节点 80 // for(int i=1;i<=n;i++) 81 // scanf("%d",&a[i]); 82 string ss; 83 for(int i=0; i<m; i++) 84 { 85 cin>>ss; 86 int aa,bb; 87 if(ss=="Q") 88 { 89 scanf("%d %d",&aa,&bb); 90 printf("%d\n",query(aa,bb,1,n,1)); 91 } 92 else 93 { 94 //把下标为aa的元素修改成bb 95 scanf("%d %d",&aa,&bb); 96 update(aa,bb,1,n,1); 97 } 98 } 99 } 100 return 0; 101 }