牛客网25 b题+最长连续上升区间+线段树

题目链接:https://www.nowcoder.com/acm/contest/158/B

给你一个长度为 n 的序列 a ,求最长的连续的严格上升区间的长度。
同时会进行 m 次修改,给定 x , y ,表示将 ax 修改为 y ,每次修改之后都要求输出答案。、
牛客网25 b题+最长连续上升区间+线段树_第1张图片

思路:开始拿到题准备用线段树的,维护区间的最长连续上升区间,但是区间合并时无法维护。后来NYX在网上找到了模板,线段树做的, (还是要多做题),当时这道题A了,自己也准备研究别人怎么维护的,因为中间去学习莫比乌斯反演了,所以一直拖到今天。

今天认真研究了别人的代码(看没有注释的代码简直是程序员的酷刑),看懂了大概思路,维护左端为开头的最长连续上升区间的长度ls,右端为结尾的最长连续上升区间的长度rs,本区间的最长连续上升区间的长度s
牛客网25 b题+最长连续上升区间+线段树_第2张图片

思考:每做一道题,就觉得对线段树的理解多了一层,自己觉得无法维护的,也是可以维护的,还是题做的太少了,努力刷题,努力进步

//区间合并维护的核心代码
node[1].s=max(node[2].s, node[3].s);
node[1].ls=node[2].ls;
node[1].rs=node[3].rs;

if(a

因为我的模板把区间的元素存在结构体中,所以还要维护区间最左边,最右边的元素,所以就重新写了模板,把元素存在一个数组中,这样就可以直接访问了

int mid=(node[i].l+node[i].r)/2;
a[mid]   //左子区间的最右元素a
a[mid+1] //右子区间的最左元素b

代码查询还写了区间查询,而这题查询整个区间,推荐另外一题查询区间的最长的连续的严格上升区间:http://acm.hdu.edu.cn/showproblem.php?pid=3308

#include 
using namespace std;
#define MAX_NODE 800000
#define MAX 200000
int Max=1<<31;

struct NODE{

    int s, ls, rs;//信息
    int l, r;//区间[l, r]

}node[MAX_NODE];

int f[MAX];//记录节点i的node结构体数组下标f[i]
int a[MAX];

void js(int i, int l, int r)
{
    node[i].l=l;
    node[i].r=r;
    node[i].ls=1;
    node[i].rs=1;
    node[i].s=1;
    if(l==r)
    {
        f[l]=i;
        return;
    }
    int mid=(l+r)/2;

    js(i*2, l, mid);
    js(i*2+1, mid+1, r);
}

void gx(int ri)
{
    if(ri==1)
        return;

    int fi=ri/2;

    node[fi].s=max(node[fi*2].s, node[fi*2+1].s);
    node[fi].ls=node[fi*2].ls;
    node[fi].rs=node[fi*2+1].rs;

    int mid=(node[fi].l+node[fi].r)/2;

    int len=node[fi].r-node[fi].l+1;//本区间长度
    int len_r=len/2;                //右子区间长度
    int len_l=len-len_r;            //左子区间长度

    if(a[mid]mid)
        cx(i*2+1, l, r);
    else
    {
        cx(i*2, l, mid);
        cx(i*2+1, mid+1, r);
    }

}

int main()
{
    int n, m;
    scanf("%d %d",&n, &m);
    js(1, 1, n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        gx(f[i]);
    }

    len=0, len_r=0;
    cx(1, 1, n);
    cout<

你可能感兴趣的:(线段树)