题意:求一个区间最长子序列的长度
对于一个区间,记录区间的最长连续子序列的长度,记录从左边开始最长连续子序列的长度,记录从右边开始最长连续子序列的长度
一个区别最长连续子序列的长度 只可能是 它的左子区间 最长连续子序列的长度 或者 它的右子区间 最长连续子序列的长度 或者 左子区间和右子区间合并后中间的长度,维护从左边开始最长连续子序列的长度和从右边开始最长连续子序列的长度就是为了求左子区间和右子区别合并后中间的长度。
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3308
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
const int MAXN = 100005;
struct Node {
int x,y;
int maxlen;
int leftlen,rightlen;
}t[MAXN << 2];
int a[MAXN];
void PushUp(int rt) {
int maxlen = 0;
//Update maxlen;
if(t[rt<<1].maxlen > maxlen) maxlen = t[rt<<1].maxlen;
if(t[rt<<1|1].maxlen > maxlen) maxlen = t[rt<<1|1].maxlen;
if(a[t[rt<<1].y] < a[t[rt<<1|1].x]) {
if(maxlen < t[rt<<1].rightlen + t[rt<<1|1].leftlen) {
maxlen = t[rt<<1].rightlen + t[rt<<1|1].leftlen;
}
}
t[rt].maxlen = maxlen;
//Update leftlen;
if(t[rt<<1].leftlen < (t[rt<<1].y - t[rt<<1].x + 1)){
t[rt].leftlen = t[rt<<1].leftlen;
}
else {
if(a[t[rt<<1].y] < a[t[rt<<1|1].x]) {
t[rt].leftlen = t[rt<<1].leftlen + t[rt<<1|1].leftlen;
}
else {
t[rt].leftlen = t[rt<<1].leftlen;
}
}
//Update rightlen;
if(t[rt<<1|1].rightlen <(t[rt<<1|1].y - t[rt<<1|1].x +1)) {
t[rt].rightlen = t[rt<<1|1].rightlen;
}
else {
if(a[t[rt<<1|1].x] > a[t[rt<<1].y]) {
t[rt].rightlen = t[rt<<1].rightlen + t[rt<<1|1].rightlen;
}
else {
t[rt].rightlen = t[rt<<1|1].rightlen;
}
}
}
void Build(int x,int y,int rt){
t[rt].x = x;
t[rt].y = y;
if(x == y) {
t[rt].maxlen = 1;
t[rt].leftlen = 1;
t[rt].rightlen = 1;
return;
}
int mid = (x + y) >> 1;
Build(x,mid,rt<<1);
Build(mid+1,y,rt<<1|1);
PushUp(rt);
}
void Update(int x,int y,int rt,int pos,int value) {
if(x == y) {
a[pos] = value;
return;
}
int mid = (x + y) >> 1;
if(mid >= pos) {
Update(x,mid,rt<<1,pos,value);
}
else {
Update(mid+1,y,rt<<1|1,pos,value);
}
PushUp(rt);
}
int ans,temp_ans,temp_right,temp_rightlen;
void Query(int x,int y,int rt,int x_edge,int y_edge) {
if(x >= x_edge && y <= y_edge) {
//Update temp_ans;
temp_ans = 0;
if(a[temp_right] < a[x]) {
temp_ans = temp_rightlen + t[rt].leftlen;
}
if(t[rt].maxlen > temp_ans) temp_ans = t[rt].maxlen;
//Update ans;
if(temp_ans > ans) ans = temp_ans;
//Update temp_rightlen;
if(t[rt].rightlen <(t[rt].y - t[rt].x +1)) {
temp_rightlen = t[rt].rightlen;
}
else {
if(a[t[rt].x] > a[temp_right]) {
temp_rightlen += t[rt].rightlen ;
}
else {
temp_rightlen = t[rt].rightlen;
}
}
// Update temp_right;
temp_right = y;
return ;
}
int mid = (x + y) >> 1;
if(mid >= x_edge)
Query(x,mid,rt<<1,x_edge,y_edge);
if(mid < y_edge)
Query(mid+1,y,rt<<1|1,x_edge,y_edge);
}
void print(int x,int y,int rt) {
printf("Left : %d Right : %d Now : %d Maxlen : %d Leftlen : %d Rightlen : %d\n",x,y,rt,t[rt].maxlen,t[rt].leftlen,t[rt].rightlen);
if(x == y) return;
int mid = (x + y) >> 1;
print(x,mid,rt<<1);
print(mid+1,y,rt<<1|1);
}
void Deal_with() {
int T,n,m;
scanf("%d",&T);
while(T--) {
scanf("%d %d",&n,&m);
memset(a,0,sizeof(a));
for(int i = 1 ; i <= n ; i++) {
scanf("%d",a+i);
//printf("%d ",a[i]);
}
//puts("");
Build(1,n,1);
//print(1,n,1);
char tempc[10];
int pos,value,Left,Right;
for(int i = 1 ; i <= m ; i++) {
//getchar();
scanf("%s",tempc);
//printf("%c\n",tempc[0]);
if(tempc[0] == 'U') {
scanf("%d %d",&pos,&value);
pos++;
Update(1,n,1,pos,value);
}
else {
scanf("%d %d",&Left,&Right);
Left ++ ; Right ++ ;
//printf("%d %d\n",Left,Right);
ans = 0; temp_ans = 0; temp_rightlen = 0; temp_right = 0;
Query(1,n,1,Left,Right);
printf("%d\n",ans);
}
}
}
}
int main(void) {
//freopen("a.in","r",stdin);
Deal_with();
return 0;
}