题意:寻找一段序列某一区间的连续最长递增子序列长度,有查询和单点修改的操作
编号从0开始,多组样例
思路点拨:节点结构体存储实际信息:mv:区间最长,lv:左端最长 rv:右端最长
关键代码:
struct Tree{
int lv,rv,mv;
int l,r;
}tree[MAXN<<2];
//结构体构建
//build函数与往常一样
void push_up(int u)
{
tree[u].lv=tree[u<<1].lv;
tree[u].rv=tree[u<<1|1].rv;
tree[u].mv=max(tree[u<<1].mv,tree[u<<1|1].mv);
int mid=(tree[u].l+tree[u].r)>>1;
int len=tree[u].r-tree[u].l+1;
if(a[mid]<a[mid+1])
{
if(tree[u].lv==len-(len>>1)) tree[u].lv+=tree[u<<1|1].lv;
if(tree[u].rv==len>>1) tree[u].rv+=tree[u<<1].rv;
tree[u].mv=max(tree[u].mv,tree[u<<1].rv+tree[u<<1|1].lv);
}
}
//push_up函数,求出mv,lv,rv 当左右段可能连起来时特殊处理
void update(int x,int y,int k)
{
if(tree[k].l==tree[k].r)
{
a[x]=y;
return;
}
int mid=(tree[k].l+tree[k].r)>>1;
if(x<=mid) update(x,y,k<<1);
else update(x,y,k<<1|1);
push_up(k);
}
//update函数,注意更改的是数组a
int query(int l,int r,int k)
{
if(l<=tree[k].l&&r>=tree[k].r)
{
return tree[k].mv;
}
int mid=(tree[k].l+tree[k].r)>>1;
int ans=0;
if(l<=mid) ans=max(ans,query(l,r,k<<1));
if(r>mid) ans=max(ans,query(l,r,k<<1|1));
if(a[mid]<a[mid+1]) ans=max(ans,min(mid-l+1,tree[k<<1].rv)+min(r-mid,tree[k<<1|1].lv));
return ans;
}
//query函数,终点直接返回mv,用临时变量ans保存最大值,注意跨子段时的处理方式
//main函数,注意输入的序号是从零开始的,而编号是从1开始的,处理前要加1.