UESTC 360 Another LCIS (线段树 维护LCIS)

题目大意:

就是对于数列S, 长度不超过1e5, 有两种操作, 第一种是将一个区间当中的所有数加上一个值, 你一种是询问一个区间中的LCIS的长度, LCIS指最长连续上升子序列


大致思路:

考虑到线段树维护两个区间的时候满足的是广义的加法, 那么要通过两个区间的LCIS的信息得到合并的区间的LCIS的信息的话, 就需要维护者6个元素:

对于每一个子区间, 维护:

1. 区间左界的值L

2. 区间右界的值R

3. 区间从左界开始能得到的LCIS的长度

4. 区间以右界作为结尾能得到的LCIS的长度

5. 不限制LCIS位置, 能得到的LCIS的长度

6. 区间长度


那么当两个区间合并的时候, 除了继承左区间的L, 左界LCIS长度, 和右区间的R, 右界LCIS长度, 以及两个区间不限制位置的LCIS最大值之外, 当左界开始的LCIS长度能达到左区间长度时, 考虑左区间右界和右区间左界的大小来判断是否能够合并得到更大的LCIS即可, 区间的L, R在区间增减的时候需要用懒惰标记记录


代码如下:

Result  :  Accepted     Memory  :  8176 KB     Time  :  211 ms

/*
 * Author: Gatevin
 * Created Time:  2015/8/18 18:40:20
 * File Name: Sakura_Chiyo.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

#define maxn 100010

struct Segment_Tree
{
    struct State
    {
        int left, mid, right;//左界开始的LCIS长度, 此区间的LCIS长度, 右界结尾的LCIS长度
        int L, R;//区间的左右端点的值
        int len;//区间长度
        State(int _l, int _m, int _r, int _L, int _R, int _len)
        {
            left = _l, mid = _m, right = _r, L = _L, R = _R, len = _len;
        }
        State(){}
    };
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    State s[maxn << 2];
    int flag[maxn << 2];//懒惰标记记录区间增量
    void pushUp(int rt)
    {
        s[rt] = State(s[rt << 1].left, max(s[rt << 1].mid, s[rt << 1 | 1].mid), s[rt << 1 | 1].right,
                      s[rt << 1].L, s[rt << 1 | 1].R, s[rt << 1].len + s[rt << 1 | 1].len);
        if(s[rt << 1].R < s[rt << 1 | 1].L)
        {
            if(s[rt << 1].left == s[rt << 1].len)
                s[rt].left = s[rt << 1].left + s[rt << 1 | 1].left;
            if(s[rt << 1 | 1].right == s[rt << 1 | 1].len)
                s[rt].right = s[rt << 1].right + s[rt << 1 | 1].right;
            s[rt].mid = max(s[rt].mid, s[rt << 1].right + s[rt << 1 | 1].left);
        }
        return;
    }
    
    void pushDown(int rt)//向下推动flag懒惰标记
    {
        if(flag[rt])
        {
            flag[rt << 1] += flag[rt];
            flag[rt << 1 | 1] += flag[rt];
            s[rt << 1].L += flag[rt];
            s[rt << 1].R += flag[rt];
            s[rt << 1 | 1].L += flag[rt];
            s[rt << 1 | 1].R += flag[rt];
            flag[rt] = 0;
        }
        return;
    }
    
    void build(int l, int r, int rt)
    {
        flag[rt] = 0;
        if(l == r)
        {
            int tmp;
            scanf("%d", &tmp);
            s[rt] = State(1, 1, 1, tmp, tmp, 1);
            return;
        }
        int mid = (l + r) >> 1;
        build(lson);
        build(rson);
        pushUp(rt);
    }
    
    void update(int l, int r, int rt, int L, int R, int value)//区间[L, R]增加value
    {
        if(l >= L && r <= R)
        {
            s[rt].L += value;
            s[rt].R += value;
            flag[rt] += value;
            return;
        }
        int mid = (l + r) >> 1;
        pushDown(rt);
        if(mid >= L) update(lson, L, R, value);
        if(mid + 1 <= R) update(rson, L, R, value);
        pushUp(rt);
        return;
    }
    
    State query(int l, int r, int rt, int L, int R)//询问区间[L, R]的LCIS长度
    {
        if(l >= L && r <= R)
            return s[rt];
        int mid = (l + r) >> 1;
        pushDown(rt);
        State sl, sr;
        bool fl = 0, fr = 0;
        if(mid >= L) sl = query(lson, L, R), fl = 1;
        if(mid + 1 <= R) sr = query(rson, L, R), fr = 1;
        //pushUp(rt);
        if(!fl) return sr;
        if(!fr) return sl;
        State ret = State(sl.left, max(sl.mid, sr.mid), sr.right,
                      sl.L, sr.R, sl.len + sr.len);
        if(sl.R < sr.L)
        {
            if(sl.left == sl.len)
                ret.left = sl.left + sr.left;
            if(sr.right == sr.len)
                ret.right = sl.right + sr.right;
            ret.mid = max(ret.mid, sl.right + sr.left);
        }
        return ret;
    }
    void solve(int cas, int n, int Q)
    {
        printf("Case #%d:\n", cas);
        build(1, n, 1);
        char op[4];
        int l, r, val;
        while(Q--)
        {
            scanf("%s", op);
            switch(op[0])
            {
                case 'q': scanf("%d %d", &l, &r);
                          printf("%d\n", query(1, n, 1, l, r).mid);
                          break;
                case 'a': scanf("%d %d %d", &l, &r, &val);
                          update(1, n, 1, l, r, val);
                          break;
            }
        }
        return;
    }
};

Segment_Tree ST;

int main()
{
    int T, n, Q;
    scanf("%d", &T);
    for(int cas = 1; cas <= T; cas++)
    {
        scanf("%d %d", &n, &Q);
        ST.solve(cas, n, Q);
    }
    return 0;
}



互联网络程序设计是指在互联网上进行程序开发和设计的过程。UESTC则是我国的一所著名高校——电子科技大学。 互联网络程序设计 uestc包含了两个主要的方面:互联网络和程序设计。互联网络是指将多个计算机网络通过通信链路互相连接起来,实现信息共享和资源共享的网络系统。程序设计是指根据需求和目标,通过编写代码和设计算法,实现计算机程序的过程。 互联网络程序设计 uestc的学习内容主要包括以下几个方面: 1. 网络知识:学习互联网络的基本概念、原理和协议,如TCP/IP协议、HTTP协议等。掌握网络编程的基本技术,能够编写网络应用程序。 2. 数据通信:学习数据通信的基本原理和技术,包括数据传输的方式、数据压缩和加密等。了解网络安全和数据保护的基本知识。 3. 程序设计:学习编程语言和开发工具,如Java、C++和Python等。掌握常用的编程技巧和方法,能够设计和实现复杂的网络应用程序。 4. Web开发:学习Web开发的基本知识和技术,包括HTML、CSS、JavaScript等。能够设计和实现交互式的Web应用程序。 5. 数据库技术:学习数据库的基本原理和技术,如SQL语言和数据库管理系统。能够设计和管理数据库,实现数据的存储和检索。 通过学习互联网络程序设计 uestc,可以掌握互联网应用开发的基本技能,具备设计和实现网络应用程序的能力。这对于目前互联网行业的人才需求来说是非常重要的,也为学生提供了广阔的就业和创业机会。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值