/*I Hate It Time Limit : 9000/3000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 0 Accepted Submission(s) : 0 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem 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 Author linle Source 2007省赛集训队练习赛(6)_linle专场 */ #include<stdio.h> int segtree[800001], n, m, data[200010], max; int Max(int a, int b) { return a>b?a:b; } void build_segtree(int l, int r, int rt) { if(l == r) { scanf("%d", &segtree[rt] );//leaf num return ; } int k = (l + r)>>1; //save time build_segtree(l, k, rt<<1); build_segtree(k + 1, r, rt<<1|1); segtree[rt] = Max(segtree[rt<<1], segtree[rt<<1|1]);//back } void update(int a, int b, int l, int r, int rt) { if(l == r) { segtree[rt] = b; return ; } int k = (l+r)>>1;//save time if(a <= k) update(a, b, l, k, rt<<1); else update(a, b, k + 1, r, rt<<1|1); segtree[rt] = Max(segtree[rt<<1], segtree[rt<<1|1]);//back } int question(int a, int b, int l , int r, int rt) { if(a <= l && r <= b)//visit { return segtree[rt]; } int sum = 0, k = (l+r)>>1; if( a <= k)//the left part sum = Max(sum, question( a, b, l , k, rt<<1) ); if(b > k )//the right part sum = Max(sum, question( a, b, k+1, r, rt<<1|1) ); return sum; } int main() { int i , j, a, b; char ch; while(scanf("%d%d", &n, &m) != EOF) { build_segtree( 1 , n , 1 ); for(i = 0; i < m; ++i) { getchar(); scanf("%c%d%d", &ch, &a, &b); if(ch == 'U')//update { update(a, b, 1, n, 1);//update the segtree } else { printf("%d\n", question(a , b , 1, n, 1) ); } } } return 0; }
题意:标准的线段树,主要操作就是点更新和区间查询最大值。
思路:线段树模板。
注意:这里有个很坑的地方,Max不要用宏定义,用函数来做,不然会超时。。。(函数调用参数是计算好的,只计算一次;宏定义没有计算,运行时每次都要计算。)