首页 > 其他分享 >P1253 扶苏的问题

P1253 扶苏的问题

时间:2023-08-29 09:56:45浏览次数:51  
标签:P1253 rs int modify 标记 tr 扶苏 问题 add

\(P1253\) 扶苏的问题

一、题目描述

给定一个长度为 \(n\) 的序列 \(a\),要求支持如下三个操作:

  1. 给定区间 \([l, r]\),将区间内每个数都修改为 \(x\)。
  2. 给定区间 \([l, r]\),将区间内每个数都加上 \(x\)。
  3. 给定区间 \([l, r]\),求区间内的最大值。

输入格式

第一行是两个整数,依次表示序列的长度 \(n\) 和操作的个数 \(q\)。
第二行有 \(n\) 个整数,第 \(i\) 个整数表示序列中的第 \(i\) 个数 \(a_i\)。
接下来 \(q\) 行,每行表示一个操作。每行首先有一个整数 \(op\),表示操作的类型。

  • 若 \(op = 1\),则接下来有三个整数 \(l, r, x\),表示将区间 \([l, r]\) 内的每个数都修改为 \(x\)。
  • 若 \(op = 2\),则接下来有三个整数 \(l, r, x\),表示将区间 \([l, r]\) 内的每个数都加上 \(x\)。
  • 若 \(op = 3\),则接下来有两个整数 \(l, r\),表示查询区间 \([l, r]\) 内的最大值。

输出格式

对于每个 \(op = 3\) 的操作,输出一行一个整数表示答案。

样例输入 #1

6 6
1 1 4 5 1 4
1 1 2 6
2 3 4 2
3 1 4
3 2 3
1 1 6 -1
3 1 6

样例输出 #1

7
6
-1

样例输入 #2

4 4
10 4 -3 -7
1 1 3 0
2 3 4 -4
1 2 4 -9
3 1 4

样例输出 #2

0

数据规模与约定

  • 对于 \(10\%\) 的数据,\(n = q = 1\)。
  • 对于 \(40\%\) 的数据,\(n, q \leq 10^3\)。
  • 对于 \(50\%\) 的数据,\(0 \leq a_i, x \leq 10^4\)。
  • 对于 \(60\%\) 的数据,\(op \neq 1\)。
  • 对于 \(90\%\) 的数据,\(n, q \leq 10^5\)。
  • 对于 \(100\%\) 的数据,\(1 \leq n, q \leq 10^6\),\(1 \leq l, r \leq n\),\(op \in \{1, 2, 3\}\),\(|a_i|, |x| \leq 10^9\)。

提示

请注意大量数据读入对程序效率造成的影响。

二、线段树解法

  • 1.其实就是用线段树进行简单的区间修改(每个数修改为\(v\), 每个数加\(v\))和 区间查询。因为有两种区间修改,所以用\(modify\)和\(add\)两个懒标记;

  • 2.两个操作之间的关系:每次一个区间若修改为\(v\),那么区间的\(add\)就要清空为\(0\)。每次下传标记先下传区间的\(modify\)再下传\(add\);

  • 3.\(pushup\)维护区间最大值;

  • 4.\(modify\)改变整个区间每个值为\(v\)之后还是得要下传\(add\)操作,因为有一部分区间可能不会被这样更新,

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;
int n, m;
int a[N];

// 线段树模板
#define int long long
#define INF 0x3f3f3f3f
#define ls u << 1
#define rs u << 1 | 1
struct Node {
    int l, r;
    int modify, add; // 两个懒标记:区间内统一修改为v,区间内统一加上v
    int mx;          // 区间最大值,结果
} tr[N << 2];

void pushup(int u) {
    tr[u].mx = max(tr[ls].mx, tr[rs].mx);
}

void build(int u, int l, int r) {
    tr[u].l = l, tr[u].r = r; // 范围

    tr[u].modify = INF; // 更新懒标记INF,更新懒标记INF
    tr[u].add = 0;      // 更新懒标记INF,加法懒标记0
    /*
      Q1:为什么modify的懒标记要设置为INF,而不是0呢?
      答:因为如果设置为0,我们就不知道到底是想整体区间都修改为0,还是默认值!我们分不清!
      同时,由于modify的值域是abs(x)=1e9,也就是可能是0,也可能是-1e9,所以,我们只能选择找一个范围外的数字做为初始值,
      才能区分开是默认值,还是人为修改值。

      Q2: 为什么add懒标记可以设置为初始化是0呢?
      答:因为对于加法而言,加零还是不加零是没有区别的,所以,人为区间加,是不会加零的。

      Q: 为什么这个对于懒标记的初始化,是在build这个递归函数的入口处就进行呢的?而对于叶子节点的赋值是在l==r的判断里?
      答:我们需要头脑中有线段树的整体架构,在每个统计区间(也可以理解为每个统计点),都是有两个懒标记:整体修改标记modify
      和整体加法标记add的,懒标记可不是作用到叶子上的,而是作用在统计节点上的!所以,对于每个需要分裂的区间,当然都需要对
      懒标记进行赋值了。
    */

    if (l == r) {
        tr[u].mx = a[l]; // 单节点时,区间最大值,准备通过pushup函数,向上汇总统计信息
        return;
    }

    int mid = (l + r) >> 1;
    build(ls, l, mid);
    build(rs, mid + 1, r);
    pushup(u);
}

void pushdown(int u) {
    // 注意:要先处理统一修改的modify懒标记,再处理add标记!

    if (tr[u].modify != INF) {                        // 如果存在modify的懒标记
        tr[ls].modify = tr[rs].modify = tr[u].modify; // 向左右儿子传递统一修改的懒标记
        tr[ls].mx = tr[rs].mx = tr[u].modify;         // 统一修改后,都是一样的值,那么左右儿子的最大值当然也是这个值
        tr[ls].add = tr[rs].add = 0;                  // 本来想向下传递加法的懒标记,这样好了,不用传递了,因为新来的要求把整体都修改成modify了
        tr[u].modify = INF;                           // modify懒标记都传递下去,处理完了,设置为默认值吧
    }

    if (tr[u].add) {             // 如果存在add的懒标记
        tr[ls].add += tr[u].add; // 左儿子的add懒标记加上新的增加出来的add
        tr[rs].add += tr[u].add; // 右儿子的add懒标记加上新的增加出来的add
        tr[ls].mx += tr[u].add;  // 左儿子的最大值加上add
        tr[rs].mx += tr[u].add;  // 右儿子的最大值加上add
        tr[u].add = 0;           // add懒标记传递完毕
    }
}

void modify(int u, int l, int r, int v) {
    if (l <= tr[u].l && r >= tr[u].r) { // 完全覆盖
        tr[u].mx = v;                   // 区间所有值修改为v,当然最大值也是v
        tr[u].modify = v;               // 全部修改为v,懒标记修改为v, 不向下继续传递
        tr[u].add = 0;                  // 整体都修改为v了,以前不管有啥add懒标记,其实都没用了,因为人家要统一修改为v
        return;
    }

    pushdown(u); // 懒标记下传时,不一定是一个懒标记,所以,不要在这里通过if进行判断决定是否进行pushdown,而是在pushdown内部完成懒标记的判定

    // 找交集

    // 方法1
    if (l <= tr[ls].r) modify(ls, l, r, v); // 左儿子的右大于等于l,表示左儿子与修改区间有交集
    if (r >= tr[rs].l) modify(rs, l, r, v); // 右儿子的左小于等于r,表示右儿子与修改区间有交集

    // 方法2
    // int mid = (tr[u].l + tr[u].r) >> 1;
    // if (l <= mid) modify(ls, l, r, v);
    // if (r > mid) modify(rs, l, r, v);

    // 修改完毕,需要向上汇总统计信息
    pushup(u);
}

void add(int u, int l, int r, int v) {  // 加v
    if (l <= tr[u].l && r >= tr[u].r) { // 完全覆盖
        tr[u].mx += v;                  // 每个人都+v,最大值肯定也要+v
        tr[u].add += v;                 // 修改整体的加法懒标记
        // Q:为什么不修改modify懒标记呢?
        // 答:当add执行时,需要把前面的都整明白后再进行add。那么,如果原来有modify的动作,就先modify,再add, 否则计算就不正确了
        return;
    }

    pushdown(u);
    // 找交集

    // 方法1
    if (l <= tr[ls].r) add(ls, l, r, v); // 左儿子的右大于等于l,表示左儿子与修改区间有交集
    if (r >= tr[rs].l) add(rs, l, r, v); // 右儿子的左小于等于r,表示右儿子与修改区间有交集

    // 方法2
    // int mid = (tr[u].l + tr[u].r) >> 1;
    // if (l <= mid) add(ls, l, r, v);
    // if (r > mid) add(rs, l, r, v);

    // 修改完毕,需要向上汇总统计信息
    pushup(u);
}

int query(int u, int l, int r) {
    if (l <= tr[u].l && r >= tr[u].r) return tr[u].mx;

    pushdown(u);

    // 方法1
    if (r < tr[rs].l) return query(ls, l, r);
    if (l > tr[ls].r) return query(rs, l, r);
    return max(query(ls, l, r), query(rs, l, r));

    //  方法2
    // int mid = (tr[u].l + tr[u].r) >> 1;
    // int res = -1e16;
    // if (l <= mid) res = max(res, query(ls, l, r));
    // if (r > mid) res = max(res, query(rs, l, r));
    // return res;
}
/*
答案:
7
6
-1
*/
signed main() {
#ifndef ONLINE_JUDGE
    freopen("P1253.in", "r", stdin);
#endif
    // 加快读入
    ios::sync_with_stdio(false), cin.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> a[i];

    build(1, 1, n);

    while (m--) {
        int op;
        int l, r, x;
        cin >> op;
        if (op == 1) {
            cin >> l >> r >> x;
            modify(1, l, r, x);
        } else if (op == 2) {
            cin >> l >> r >> x;
            add(1, l, r, x);
        } else {
            cin >> l >> r;
            printf("%lld\n", query(1, l, r));
        }
    }
    return 0;
}

标签:P1253,rs,int,modify,标记,tr,扶苏,问题,add
From: https://www.cnblogs.com/littlehb/p/17663960.html

相关文章

  • 安防视频监控平台EasyCVR视频集中存储平台接入RTSP设备出现离线情况的问题解决方案
    安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力,也具备接入AI智能分析的......
  • (原创)解决串口上无登录提示符,无法登录的问题
    问题描述:      制作好rootfs后,kernel能够引导rootfs进入到系统,但是串口上最终却没有登入提示符。使用SSH或者Telnet可以登入系统。无法使用串口进行登录系统,使用起来不方便。问题分析:      对照启动流程梳理,发现所设置的运行级别为3下的所有启动脚本均已执行(rc3.d),......
  • 银河麒麟SP2 auditd服务内存泄露问题
    这几天遇到基于海光服务器的银河麒麟V10SP2版本操作系统出现内存无故增长问题。排查发现auditd服务,占用了大量内存。我的环境是银河麒麟V10SP2524,audit版本audit-3.0-5.se.06==5037==HEAPSUMMARY:==5037==inuseatexit:3,022bytesin210blocks==5037==to......
  • 性能测试-网络问题定位
    目录总结:1、网络问题显示2、网络问题调优-keepalive-注册表三、服务端修改端口号范围四、检查带宽五、网卡 正文总结:1、网络问题显示项目实战:报错java.net.BindException:Addressalreadyinuse:connectHttpHostConnectException:Connectto192.168.****:8......
  • QT连接MySql关于驱动问题
    今天分享一下在qt中连接数据库遇到的一些问题,主要是mysql驱动以及mysql动态库加载1.环境变量配置一下mysql和QT的环境变量,这个比较简单,各位自行百度。2.编译mysql驱动用QT打开mysql.pro文件,在第六行首加上#,然后在末尾加入:win32:LIBS+=-LD:/MySql/mysql-8.1.0-winx64/lib-l......
  • 剑指 Offer 10- II. 青蛙跳台阶问题(简单)
    题目:classSolution{public:intnumWays(intn){vector<int>dp(n+1,1);for(inti=2;i<=n;i++){dp[i]=(dp[i-1]+dp[i-2])%1000000007;}returndp[n];}};......
  • require在vite不能用的问题(做手机短信弄滑块验证时候碰到)
    第一步:yarnadd-Dvite-plugin-require-transform或  npm ivite-plugin-require-transform --save-dev第二步:在vite.config.js中配置import{defineConfig}from'vite'importrequireTransformfrom'vite-plugin-require-transform';exportdefault......
  • VSCode下载慢问题解决
    1.打开vscode官网浏览器搜索:vscodedownload或打开该网站https://code.visualstudio.com/Download/2.选中系统对应的版本 3.复制下载链接地址 4.修改链接地址将复制后的链接地址的域名(上图https后面框起来的那块)修改为 vscode.cdn.azure.cn最后变成类似:https......
  • 遗传算法解决航路规划问题(MATLAB)
    遗传算法文章部分图片和思路来自司守奎,孙兆亮《数学建模算法与应用》第二版定义:遗传算法是一种基于自然选择原理和自然遗传机制的搜索(寻优)算法,模拟自然界中的声明进化机制,在人工系统中实现特定目标的优化。本质其实就是群体搜索技术,根据适者生存的原则逐代进化,最终得到最优解......
  • 视频汇聚/视频云存储/视频监控管理平台EasyCVR安全检查的相关问题及解决方法
    安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力,也具备接入AI智能分析的......