线段树——区间合并 单点更新 模板
http://acm.hdu.edu.cn/showproblem.php?pid=3308
#include<algorithm> #include<cstring> #include<cstdio> #include<iostream> using namespace std; struct node{ int ls,rs,ms; //ls 区间左连续序列的长度 }; node no[8*100000]; int a[8*100000]; void pushup(int cr,int l,int r){ no[cr].ls=no[cr<<1].ls; no[cr].rs=no[cr<<1|1].rs; no[cr].ms=max(no[cr<<1|1].ms,no[cr<<1].ms);; int mid=(l+r)/2; if( no[cr].ls==mid-l+1 && a[mid]<a[mid+1] ){ //区间左连续与 右子区间左连续 no[cr].ls+=no[cr<<1|1].ls; } if( no[cr].rs==r-mid && a[mid]<a[mid+1] ){ //区间右连续与 左子区间右连续 no[cr].rs+=no[cr<<1].rs; } if(a[mid]<a[mid+1]) no[cr].ms=max(no[cr].ms,no[cr<<1].rs+no[cr<<1|1].ls); } void build(int l,int r,int cr){ if(l==r){ no[cr].ls=no[cr].rs=no[cr].ms=1; return ; } int mid=(l+r)/2; build(l,mid,cr<<1); build(mid+1,r,cr<<1|1); pushup(cr,l,r); } int query(int l,int r,int cr,int L,int R){ if(l==L&&r==R){ return no[cr].ms; } int mid=(L+R)/2,ans=0; if( r<=mid ){ //左边找 ans=query(l,r,cr<<1,L,mid); } else if(l>mid){ //或右边找 ans=query(l,r,cr<<1|1,mid+1,R); } else { //中间找 ans=max(query(l,mid,cr<<1,L,mid),query(mid+1,r,cr<<1|1,mid+1,R)); //左边最长,右边最长 if(a[mid]<a[mid+1]) ans=max( min( no[cr<<1].rs, mid-l+1 )+min( no[cr<<1|1].ls,r-mid),ans); //中间最长 } return ans; } void update(int p,int val,int L,int R,int cr){ if(L==p&&R==p){ a[p]=val; return ; } int mid=(L+R)/2; if(p<=mid) update(p,val,L,mid,cr<<1); else update(p,val,mid+1,R,cr<<1|1); pushup(cr,L,R); } int main(){ int t; scanf("%d",&t); while(t--){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } build(1,n,1); getchar(); while(m--){ char s[5]; scanf("%s",s); if(s[0]=='U'){ int b,c; scanf("%d%d",&b,&c); update(b+1,c,1,n,1); }else { int b,c; scanf("%d%d",&b,&c); b++,c++; printf("%d\n",query(b,c,1,1,n)); } } } }