这题明显是线段树基本区间合并,由于第一次写也遇到了不少问题,下面将赘述。。
首先对于区间合并问题,tr里面要有rsum,lsum,msum,分别表示左连续最大,右连续最大,和区间最大,为什么这么表示,当然是为了合并操作。
先说pushup部分,不是简单的sum或者max了,按套路来,如果合并有特殊条件要加特殊条件,对于这道题要加判断arr[mi]和arr[mi+1],
由于这道题没有pushdown,所以还算简单,下一步打算做一个有pushdown的,
queue里面也有技巧,就是当mid在s和t中间时要用min确保合并的时候(当然是符合合并条件时)得到正确答案,以防多算了不在s和t中间的。
midify就是简单的midify加pushup就可以了显而易见。
由于是第一道区间合并还有理解不透彻的地方,希望继续努力,蒟蒻加油。。。
#include<stdio.h> #include<iostream> #include<cstring> using namespace std; const int MAX=1000000; struct pr { int msum,lsum,rsum; int left,right; }tr[MAX+10]; int n; inline int ll(int k) {return 2*k;} //左边的下标 inline int rr(int k) {return 2*k+1;} //右边的下标 inline int mid(int kk1,int kk2) {return (kk1+kk2)>>1;} int arr[MAX]; void pushup(int k){//m=r-l+1; int l=tr[k].left,r=tr[k].right; int mi=mid(l,r); tr[k].lsum =tr[ll(k)].lsum; tr[k].rsum =tr[rr(k)].rsum;//如果合并有条件则加条件 if(arr[mi]<arr[mi+1]){ if (tr[k].lsum == mi-l+1) tr[k].lsum+=tr[rr(k)].lsum; if (tr[k].rsum == r-mi) tr[k].rsum+=tr[ll(k)].rsum; tr[k].msum = max(tr[rr(k)].lsum+tr[ll(k)].rsum,max(tr[ll(k)].msum,tr[rr(k)].msum)); return; } tr[k].msum = max(tr[ll(k)].msum,tr[rr(k)].msum); } void build(int k,int s,int t) { tr[k].left=s;tr[k].right=t; if(s==t) {tr[k].lsum=tr[k].rsum=tr[k].msum=1;return;} build(ll(k),s,mid(s,t)); build(rr(k),mid(s,t)+1,t); pushup(k); //pushup return; } void modify(int k,int s,int x) { int l=tr[k].left,r=tr[k].right; if(l==r){ arr[s]=x; return ; } int mi=mid(l,r); if(s<=mi) modify(ll(k),s,x); else if(s>mi) modify(rr(k),s,x); pushup(k); } int query(int k,int s,int t) { int l=tr[k].left,r=tr[k].right; if(l==s&&r==t) return tr[k].msum; int mi=mid(l,r); int res=0; if (t<=mi) res=query(ll(k),s,t); else if(s>mi) res=query(rr(k),s,t); else { res=max(query(ll(k),s,mi),query(rr(k),mi+1,t)); if(arr[mi]<arr[mi+1]){ res=max(res,min(mi-s+1,tr[ll(k)].rsum)+min(t-mi,tr[rr(k)].lsum)); } } return res; } int main(){ int t; cin>>t; int n,m; while(t--){ memset(tr,0,sizeof(tr)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&arr[i]); } build(1,1,n); char c[2]; int a,b; for(int i=0;i<m;i++){ scanf("%s%d%d",c,&a,&b); if(c[0]=='Q'){ printf("%d\n",query(1,a+1,b+1)); } else{ modify(1,a+1,b); } } } return 0; }