题意:动态修改查询区间最长连续上升序列,注意:是连续的。
思路:线段树区间合并的经典题,做这题最重要的是要写好pushUp函数,写pushUp函数需要递推一下,题目是求连续最长的子序列,所以可以知道每个区间的最长子序列有三种情况:1.最长子序列在左子区间;2.最长子序列在右子区间;3.最长子序列由左子区间和右子区间组成;前面两种情况直接更新到上一层即可,第三种情况则需将左子区间和右子区间合并,每个结点开辟两个变量L,R(记录长度); L记录以本区间第一个元素开始的最长连续上升子序列,R记录以本区间最右元素结束的最长上升子序列,然后合并的时候比较一下看是否需要更新就可以了;
另外,在询问的时候,也需要将左右两个子区间合并,看是否有最大值。
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int T, n, q, num[N], res;
struct segTree{
int lc, rc, maxLen, R, L;
}arr[N * 4];
inline int lson(int idx){
return (idx << 1);
}
inline int rson(int idx){
return ((idx << 1) | 1);
}
void pushUp(int idx){
arr[idx].maxLen = max(arr[lson(idx)].maxLen, arr[rson(idx)].maxLen);
arr[idx].R = arr[rson(idx)].R;
arr[idx].L = arr[lson(idx)].L;
if(num[arr[rson(idx)].lc] > num[arr[lson(idx)].rc]){
arr[idx].maxLen = max(arr[idx].maxLen, arr[lson(idx)].R + arr[rson(idx)].L);
if(arr[rson(idx)].R == arr[rson(idx)].rc - arr[rson(idx)].lc + 1)
arr[idx].R = arr[lson(idx)].R + arr[rson(idx)].R;
if(arr[lson(idx)].L == arr[lson(idx)].rc - arr[lson(idx)].lc + 1)
arr[idx].L = arr[lson(idx)].L + arr[rson(idx)].L;
}
}
void build(int idx, int l, int r){
arr[idx].lc = l, arr[idx].rc = r;
if(l == r){
arr[idx].maxLen = 1, arr[idx].R = 1, arr[idx].L = 1;
return ;
}
int mid = (l + r) >> 1;
build(lson(idx), l, mid);
build(rson(idx), mid + 1, r);
pushUp(idx);
}
void update(int idx, int loc){
if(arr[idx].lc > loc || loc > arr[idx].rc)
return ;
if(arr[idx].lc == arr[idx].rc)
return;
update(lson(idx), loc);
update(rson(idx), loc);
pushUp(idx);
}
void query(int idx, int l, int r){
if(arr[idx].lc > r || l > arr[idx].rc)
return ;
if(arr[idx].lc >= l && arr[idx].rc <= r){
res = max(res, arr[idx].maxLen);
return ;
}
query(lson(idx), l, r);
query(rson(idx), l, r);
if(num[arr[rson(idx)].lc] > num[arr[lson(idx)].rc]){
int x, y;
if(arr[lson(idx)].rc - arr[lson(idx)].R < l)
x = arr[lson(idx)].rc - l + 1;
else
x = arr[lson(idx)].R;
if(arr[rson(idx)].lc + arr[rson(idx)].L > r)
y = r - arr[rson(idx)].lc + 1;
else
y = arr[rson(idx)].L;
res = max(res, x + y);
}
}
int main(){
cin >> T;
while(T--){
int i;
cin >> n >> q;
for(i = 1;i <= n;i++)
scanf("%d", &num[i]);
build(1, 1, n);
while(q--){
int l, r;
char ord[5];
scanf("%s%d%d", ord, &l, &r);
l++, r++;
if(ord[0] == 'Q'){
res = 1;
query(1, l, r);
printf("%d\n", res);
}else{
r--;
num[l] = r;
update(1, l);
}
}
}
return 0;
}