题目:http://acm.hdu.edu.cn/showproblem.php?pid=3308
线段树,区间合并的入门题啊。蛮好的。更新直接更新到底,查询注意。合并的情况。这个地方错了2次。
下面是AC代码:
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 100000+100;
int a[maxn];
struct node{
int l,r;
int msum,lsum,rsum,lv,rv;
}T[maxn<<2];
void pushup(int id,int l,int r){
int m=(l+r)>>1;
T[id].lv=T[id<<1].lv; T[id].rv=T[id<<1|1].rv;
T[id].msum=max(T[id<<1].msum,T[id<<1|1].msum);
if(T[id<<1].rv<T[id<<1|1].lv){
T[id].msum=max(T[id].msum,T[id<<1].rsum+T[id<<1|1].lsum);
}
T[id].lsum=T[id<<1].lsum;
T[id].rsum=T[id<<1|1].rsum;
if(T[id<<1].lsum==m-l+1&&T[id<<1].rv<T[id<<1|1].lv){
T[id].lsum+=T[id<<1|1].lsum;
}
if(T[id<<1|1].rsum==r-m&&T[id<<1].rv<T[id<<1|1].lv){
T[id].rsum+=T[id<<1].rsum;
}
}
void build(int id,int l,int r){
T[id].l=l;T[id].r=r;
if(l==r) {
T[id].lv=T[id].rv=a[l];
T[id].msum=T[id].lsum=T[id].rsum=1;
return;
}
int m=(l+r)>>1;
build(id<<1,l,m); build(id<<1|1,m+1,r);
pushup(id,l,r);
}
void update(int id,int l,int val){
if(T[id].l==l&&T[id].r==l){
T[id].lv=T[id].rv=val;
T[id].msum=T[id].lsum=T[id].rsum=1;
return;
}
int m=(T[id].l+T[id].r)>>1;
if(m>=l) update(id<<1,l,val);
else update(id<<1|1,l,val);
pushup(id,T[id].l,T[id].r);
}
int query(int id,int l,int r){
if(T[id].l==l&&T[id].r==r){
return T[id].msum;
}
int m=(T[id].l+T[id].r)>>1;
if(m>=r){
return query(id<<1,l,r);
}
else if(l>m){
return query(id<<1|1,l,r);
}
else{
int a=query(id<<1,l,m);
int b=query(id<<1|1,m+1,r);
if(T[id<<1].rv<T[id<<1|1].lv){
int lsum=min(T[id<<1].rsum,m-l+1); int rsum=min(T[id<<1|1].lsum,r-m);
return max(a,max(lsum+rsum,b));
}
else{
return max(a,b);
}
}
}
int main(){
int t,n,m,l,r; char str[200];
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
for(int i=0;i<m;i++){
scanf("%s%d%d",str,&l,&r);
if(str[0]=='Q'){
l++;r++;
printf("%d\n",query(1,l,r));
}
else{
l++; update(1,l,r);
}
}
}
return 0;
}