给定10^5个数,区间查询严格上升的最长连续序列长度,点更新某个数.
每个区间记录包括左边最长,右边最长,全局最长即可...
code:
#include <cstdio>
#include <cstring>
#include <cassert>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
#define N 100050
#define LL L, m, c<<1
#define RR m+1, R, c<<1|1
#define max(a, b) a>b?a:b
struct node{int l, r, a; };
int dt[N], lt[N<<2], rt[N<<2], at[N<<2];
// data, left, right, all
void pushUp(int L, int R, int c){
int m=(L+R)>>1;
lt[c]=lt[c<<1]; rt[c]=rt[c<<1|1];
at[c]=max(at[c<<1], at[c<<1|1]);
if(dt[m]<dt[m+1]){
if(lt[c<<1]==m-L+1) lt[c]+=lt[c<<1|1];
if(rt[c<<1|1]==R-m) rt[c]+=rt[c<<1];
at[c]=max(at[c], rt[c<<1]+lt[c<<1|1]);
}
}
// seg build
void build(int L, int R, int c)
{
if(L==R) {
scanf("%d", &dt[L]);
lt[c]=rt[c]=at[c]=1;
return;
}
int m=(L+R)>>1;
build(LL);
build(RR);
pushUp(L, R, c);
}
// point update
void update(int l, int v, int L, int R, int c)
{
if(l<=L && R<=l){
dt[l]=v; return;
}
int m=(L+R)>>1;
if(l<=m) update(l, v, LL);
else update(l, v, RR);
pushUp(L, R, c);
}
// seg ques
node ques(int l, int r, int L, int R, int c)
{
node lv, rv, av;
av.a=av.l=av.r=1;
if(l==L && R==r) {
av.a=at[c];
av.l=lt[c];
av.r=rt[c];
return av;
}
int m=(L+R)>>1;
if(r<=m) return ques(l, r, LL);
else if(l>m) return ques(l, r, RR);
else {
lv=ques(l, m, LL);
rv=ques(m+1, r, RR);
av.l=lv.l; av.r=rv.r;
av.a=max(lv.a, rv.a);
if(dt[m]<dt[m+1]) {
if(lv.l==m-l+1) av.l+=rv.l;
if(rv.r==r-m) av.r+=lv.r;
av.a=max(av.a, lv.r+rv.l);
}
return av;
}
}
int main()
{
int t, n, q;
scanf("%d", &t);
while(t--){
scanf("%d%d", &n, &q);
build(1, n, 1);
char ch[2];
int a, b;
while(q--){
scanf("%s%d%d", ch, &a, &b);
if(*ch=='Q')
printf("%d\n", ques(a+1, b+1, 1, n, 1).a);
else if(*ch=='U') update(a+1, b, 1, n, 1);
else assert(0>1);
}
}
return 0;
}