HDOJ(HDU).1754 I Hate It (ST 单点替换 区间最大值)
题意分析
从题目中可以看出是大数据的输入,和大量询问。基本操作有:
1.Q(i,j)代表求区间max(a[k]) k∈[i,j];
2.U(i,j)代表a[i] = j;
对于询问U,用单点替换的操作维护线段树。对于询问Q,那么除了叶子节点,其他的节点应该保存的是左子树和右子树的最大值,因此pushup函数应该是对最大值的一个维护,query的时候找出的应该是最大值,故改为ans = max(……) 即可。
代码总览
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define nmax 200005
using namespace std;
int a[nmax],add[nmax<<2],sum[nmax<<2];
void pushup(int rt)
{
sum[rt] = max(sum[rt<<1] ,sum[rt<<1|1]);
}
void pushdown(int rt, int ln, int rn)
{
if(add[rt]){
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
sum[rt<<1]+=add[rt]*ln;
sum[rt<<1|1]+=add[rt]*rn;
add[rt] = 0;
}
}
void build(int l ,int r, int rt)
{
if(l == r){
sum[rt] = a[l];
return;
}
int m = (l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt);
}
void updatep(int L, int c, int l, int r, int rt)
{
if(l == r){
sum[rt] = c;
return;
}
int m = (l+r)>>1;
pushdown(rt,m-l+1,r-m);
if(L<=m) updatep(L,c,l,m,rt<<1);
else updatep(L,c,m+1,r,rt<<1|1);
pushup(rt);
}
void updatei(int L, int R, int c, int l, int r, int rt)
{
if( l>=L && r<= R){
sum[rt]+=c*(r-l+1);
add[rt]+=c;
return;
}
int m = (l+r)>>1;
pushdown(rt,m-l+1,r-m);
if(L<=m) updatei(L,R,c,l,m,rt<<1);
if(R>m) updatei(L,R,c,m+1,r,rt<<1);
pushup(rt);
}
int query(int L, int R, int l ,int r, int rt)
{
if(L<=l && r<=R){
return sum[rt];
}
int m = (l+r)>>1;
pushdown(rt,m-l+1,r-m);
int ANS =0;
if(L<=m) ANS = max( query(L,R,l,m,rt<<1),ANS);
if(R>m) ANS = max(query(L,R,m+1,r,rt<<1|1),ANS);
return ANS;
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m;
while(scanf("%d%d",&n,&m)!= EOF){
for(int i =1;i<=n; ++i) scanf("%d",&a[i]);
build(1,n,1);
char com;
for(int i = 1;i<=m;++i){
scanf(" %c",&com);
if(com == 'Q'){
int L,R;
scanf("%d%d",&L,&R);
printf("%d
",query(L,R,1,n,1));
}else{
int L,c;
scanf("%d%d",&L,&c);
updatep(L,c,1,n,1);
}
}
}
return 0;
}