题意:长度为N的数组,进行m次操作,
分为两种操作:
操作1:U A B 把位置A上的更新为B,
操作2: Q A B 输出[A,B]上的最长连续上升子序列
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308
思路:
操作1,:单点更新
操作2:求连续的上升子序列,区间合并,
线段树节点维护三个值,这个子序列的左边开始的个数,右边开始的个数,这个区间的子序列的个数
和poj 3368多了一点在于单点更新~~~
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define maxn 100010
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int n,m;
int val[maxn];
struct segnode{
int lnum,rnum,num;
};
segnode tree[maxn<<2];
void PushUp(int rt,int l,int r){
int m = (l + r)/2;
tree[rt].lnum = tree[rt<<1].lnum;
tree[rt].rnum = tree[rt<<1|1].rnum;
tree[rt].num = max(tree[rt<<1].num , tree[rt<<1|1].num);
if(val[m] < val[m+1]){
if(tree[rt<<1].lnum == (m - l + 1))
tree[rt].lnum += tree[rt<<1|1].lnum;
if(tree[rt<<1|1].rnum == (r - m))
tree[rt].rnum += tree[rt<<1].rnum;
tree[rt].num = max(tree[rt].num,(tree[rt<<1].rnum + tree[rt<<1|1].lnum));
}
}
void build(int l,int r,int rt){
if(l == r){
tree[rt].lnum = 1;
tree[rt].rnum = 1;
tree[rt].num = 1;
return ;
}
int m = (l + r)/2;
build(lson);
build(rson);
PushUp(rt,l,r);
}
void update(int pos,int c,int l,int r,int rt){
if(l == r){
val[pos] = c;
return ;
}
int m = (l + r)/2;
if(pos <= m) update(pos,c,lson);
else update(pos,c,rson);
PushUp(rt,l,r);
}
int query(int L,int R,int l,int r,int rt){
if(L <= l && r <= R){
return tree[rt].num;
}
int m = (l + r)/2;
if(R <= m) return query(L,R,lson);
else if(L > m) return query(L,R,rson);
else{
int lans = query(L,m,lson);
int rans = query(m+1,R,rson);
if(val[m] < val[m+1]){
int temp = min(tree[rt<<1].rnum ,(m - L + 1)) + min(tree[rt<<1|1].lnum , R - m);
return max(temp,max(lans,rans));
}
else{
return max(lans,rans);
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
build(1,n,1);
while(m--){
char op[10];
int a,b;
scanf("%s %d %d",op,&a,&b);
if(op[0]=='U'){
update(a+1,b,1,n,1);
}
else{
printf("%d\n",query(a+1,b+1,1,n,1));
}
}
}
return 0;
}