标签:单点 int 线段 mid 查询 HDU1754 ans Hate op

题目链接:传送门
解题思路:从题目中我们很明显知道只有两种操作,第一种是查询\([A,B]\)范围内学生成绩的最大值,典型的RMQ,第二种操作是将A的成绩改为B,而不是改为B的成绩,请仔细体会。(当然样例都能看得出来),我们线段树只需要保存区间最大值,在updata和pushup两函数操作就行,最后注意多组输入,该题为线段树经典板子题。
Code:
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 2000005;
int n,m;
int a[N],tree[N << 2];
void push_up(int k) {
tree[k] = max(tree[k<<1],tree[k<<1|1]);//把父节点的值更新为两子节点中的最大值
}
void build(int k, int l,int r) {
if(l == r) {
tree[k] = a[l];
}
else {
int mid = l + ((r-l)>>1);
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
push_up(k);
}
}
void updata(int p,int v,int l,int r,int k) {
if(l == r) {
a[p] += v, tree[k] += v;
}
else {
int mid = l + ((r-l)>>1);
if(p <= mid) {
updata(p,v,l,mid,k<<1);
}
else {
updata(p,v,mid+1,r,k<<1|1);
}
push_up(k);
}
}
int query(int L, int R,int l,int r,int k) {
if(L <= l && R >= r) {
return tree[k];
}
else {
int ans = -INF;
int mid = l+r >>1;
if(L <= mid) {//如果查询区间在左边
ans = max(ans,query(L,R,l,mid,k<<1));
}
if(R > mid) {//查询区间在右边
ans = max(ans,query(L,R,mid+1,r,k<<1|1));
}
return ans;
}
}
int main()
{
while(~scanf("%d%d",&n,&m)) {
for(int i = 1;i <= n; ++i) {
scanf("%d",&a[i]);
}
build(1,1,n);
char op;
int l,r;
while(m--) {
cin>>op;
if(op == 'Q') {
scanf("%d%d",&l,&r);
printf("%d\n",query(l,r,1,n,1));
}
else if(op == 'U'){
scanf("%d%d",&l,&r);
updata(l,r-a[l],1,n,1);
}
}
}
return 0;
}
标签:单点,int,线段,mid,查询,HDU1754,ans,Hate,op 来源: https://www.cnblogs.com/Mangata/p/14290276.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。
