题目: 传送门
思路:
之前遇到的第一个区间合并题,二刷感觉真的好麻烦,wa了好多发,主要是忘记了要怎么区间合并了(大哭).
using namespace std;
const int maxn = 1e5+7;
struct Tree
{
int ls,rs,ms;
};
int n,m;
Tree tr[maxn<<2];
int a[maxn];
void pushup(int l,int r,int num) {
int mid = (l+r) >>1;
tr[num].ls = tr[num<<1].ls;
tr[num].rs = tr[num<<1|1].rs;
tr[num].ms = max(tr[num<<1].ms,tr[num<<1|1].ms);
if( a[mid] < a[mid+1]) {
tr[num].ms = max(tr[num].ms,tr[num<<1].rs + tr[num<<1|1].ls);
if(tr[num].ls == (mid-l+1)) tr[num].ls += tr[num<<1|1].ls;
if(tr[num].rs == (r - mid)) tr[num].rs += tr[num<<1].rs;
}
return ;
}
void build(int l,int r,int num) {
if(l == r) {
tr[num].ls = tr[num].rs = tr[num].ms= 1;
return ;
}
int mid = (l+r) >>1;
build(l,mid,num<<1);
build(mid+1,r,num<<1|1);
pushup(l,r,num);
return ;
}
void modify(int l,int r,int num,int pos) {
if( pos <l || r <pos ) return ;
if( pos <=l && r <= pos ) return ;
int mid = (l+r) >>1;
if( mid >= pos ) modify(l,mid,num<<1,pos);
if( mid < pos ) modify(mid+1,r,num<<1|1,pos);
pushup(l,r,num);
return ;
}
void quriy(int l,int r,int num,int le,int ri,int& ans) {
if(ri < l || r< le) return ;
if( l == r) return ;
int mid = (l+r) >>1;
int les = mid - tr[num<<1].rs+1;
int ris = mid+tr[num<<1|1].ls;
if( mid+1 < le || mid >ri ) {
if(mid<le) quriy(mid+1,r,num<<1|1,le,ri,ans);
else quriy(l,mid,num<<1,le,ri,ans);
return ;
}
if( a[mid] < a[mid+1]) ans = max(ans,min(ris,ri) - max(les,le)+1);
else ans = max(ans,max(min(mid,ri)-max(les,le), min(ris,ri)-max(les,mid+1))+1);
if( le <= l && r<= ri) ans = max(ans,tr[num].ms);
if( tr[num<<1].ms > ans) quriy(l,mid,num<<1,le,ri,ans);
if( tr[num<<1|1].ms>ans) quriy(mid+1,r,num<<1|1,le,ri,ans);
}
int main() {
int t;
scanf("%d",&t);
while(t--) {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,n,1);
while(m--) {
char op;int l;int r;
scanf(" %c%d%d",&op,&l,&r);
if( op == 'U') {
a[l+1] = r;
modify(1,n,1,l+1);
}
else {
int ans = 1;
quriy(1,n,1,l+1,r+1,ans);
printf("%d\n",ans);
}
}
}
return 0;
}