IHateIt
I
H
a
t
e
I
t
Problem Description
很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。
这让很多学生很反感。
不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。
Input
本题目包含多组测试,请处理到文件结束。
在每个测试的第一行,有两个正整数 N<0,200000> 和 M<0,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
HintHuge input,the C function scanf() will work better than cin
思路:线段树的区间查找最大值和单点更新。
开始的时候想都没想直接暴力刚 TLE得理所当然,询问和单点更新交替操作不爆掉才怪。。。第一次上手用一发线段树
#include<bits/stdc++.h>
using namespace std;
const int Maxi = 5416452;
int segTree[4*Maxi+10];
void PushUpNode(int node){
segTree[node]=max(segTree[node<<1],segTree[node<<1|1]);
}
void bulid(int begin,int end,int node){
if(begin==end){
scanf("%d",&segTree[node]);
return ;
}
int mid = (begin+end)>>1;
bulid(begin,mid,node<<1);
bulid(mid+1,end,node<<1|1);
PushUpNode(node);
}
void updatedata(int p,int sc,int left,int right,int node) {
if (left==right) {
segTree[node] = sc;
return ;
}
int mid = (left + right)>>1;
if (p <= m) updatedata(p , sc , left, mid, node<<1);
else updatedata(p,sc,mid+1, right,node<<1|1);
PushUpNode(node);
}
int query(int begin,int end,int left,int right,int node){
if(begin<=left&&right<=end){
return segTree[node];
}
int mid =(left+right)>>1;
int ret = 0;
if(begin<=mid){
ret = max(ret,query(begin,end,left,mid,node<<1));
}
if(mid<end){
ret = max(ret,query(begin,end,mid+1,right,node<<1|1));
}
return ret;
}
int main(){
int n , m;
while (~scanf("%d%d",&n,&m)) {
bulid(1 , n , 1);
while (m --) {
char op[2];
int a , b;
scanf("%s%d%d",op,&a,&b);
if (op[0] == 'Q') printf("%d\n",query(a , b , 1 , n , 1));
else updatedata(a , b , 1 , n , 1);
}
}return 0;
}
在学习线段树的过程中,窝觉得低层节点大概就是mm个的样子那数组只要开2*mm-1就好了啊。。对开 *4的空间很是费解。。然后神犇甩给窝的链接也还是不求甚解。。点这里。。。4倍空间的解释
然后神犇又告诉窝其实线段树是可以开二倍空间的!在构造树的时候有好多节点并没有用得上
比如下面代码运行起来之后。。
#include<bits/stdc++.h>
using namespace std;
const int maxi = 1213213;
int segTree[maxi*4+10];
int array[maxi];
void PushUp(int node){
segTree[node]=max(segTree[node<<1],segTree[node<<1|1]);
}
void bulid(int left ,int right,int node){
if(left==right){
segTree[node]=array[left];
return;
}
int mid = (left+right)>>1;
bulid(left,mid,node<<1);
bulid(mid+1,right,node<<1|1);
PushUp(node);
}
int main(){
array[1]=1,array[2]=2,array[3]=2,array[4]=4,array[5]=1,array[6]=3;
bulid(1,6,1);
for(int i = 1;i<=13;i++){
cout<<"segTree"<<i<<" "<<segTree[i]<<endl;
}return 0;
}
显然NODE10和11是没有用到。。所以有没有一种方法,能直接把线段树所有的节点,恰好对应到n个连续空间上?
留待更新…
int ID(int l,int r){
return l+r|l!=r;
}