题目: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; }