洛谷P3373

线段树模板题,主要对懒标的处理要求比较高。
有三种操作:

  1. 区间加法
  2. 区间乘法
  3. 区间求和查询

tips:我们对一个区间进行乘k操作的时候,他之前可能存在加法lazy还没pushdown,这时候,加法lazy和乘法lazy都需要乘k。因为这个lazy是为儿子节点准备的,儿子还没进行加法操作,这次的乘法肯定也会作用于前面的加法。

另外,线段树的一些基本知识点漏洞这次也暴露了出来: pushdown操作,我们知道,每个结点的懒标都是为儿子结点准备的,所以在查询/修改到x结点的时候不需要pushdown,即将查询/修改x的儿子结点的时候才需要pushdown。

AC代码:

long long a[100010];
long long mod;
long long n, m;
struct node
{long long k, l, r, sum, lazy1, lazy2; //lazy1 乘法懒标,lazy2加法懒标
} tr[400040];void update(long long k)
{tr[k].sum = (tr[k * 2].sum + tr[k * 2 + 1].sum) % mod;
}
void build(long long k, long long l, long long r)
{tr[k].l = l;tr[k].r = r;tr[k].lazy1 = 1;tr[k].lazy2 = 0;if (tr[k].l == tr[k].r){tr[k].sum = a[l] % mod;return;}long long mid = l + r >> 1;build(k * 2, l, mid);build(k * 2 + 1, mid + 1, r);update(k);
}inline void pushdown(long long k)
{tr[k * 2].sum = (tr[k * 2].sum * tr[k].lazy1 + (tr[k * 2].r - tr[k * 2].l + 1) * tr[k].lazy2) % mod;tr[k * 2 + 1].sum = (tr[k * 2 + 1].sum * tr[k].lazy1 + (tr[k * 2 + 1].r - tr[k * 2 + 1].l + 1) * tr[k].lazy2) % mod;tr[k * 2].lazy1 = (tr[k * 2].lazy1 * tr[k].lazy1) % mod;tr[k * 2 + 1].lazy1 = (tr[k * 2 + 1].lazy1 * tr[k].lazy1) % mod;tr[k * 2].lazy2 = (tr[k].lazy1 * tr[k * 2].lazy2 + tr[k].lazy2) % mod;tr[k * 2 + 1].lazy2 = (tr[k].lazy1 * tr[k * 2 + 1].lazy2 + tr[k].lazy2) % mod;tr[k].lazy1 = 1;tr[k].lazy2 = 0;
}void change(long long k, long long l, long long r, long long opt, long long val)
{if (tr[k].l == l && tr[k].r == r){if (opt == 1){tr[k].sum = (tr[k].sum * val) % mod;tr[k].lazy1 = (tr[k].lazy1 * val) % mod;tr[k].lazy2 = (tr[k].lazy2 * val) % mod; //!做乘法的时候对lazy1和lazy2都要改变}else{tr[k].sum = (tr[k].sum + val * (tr[k].r - tr[k].l + 1)) % mod;tr[k].lazy2 = (tr[k].lazy2 + val) % mod;}return;}pushdown(k);long long mid = tr[k].l + tr[k].r >> 1;if (r <= mid){change(k * 2, l, r, opt, val);}else if (l > mid){change(k * 2 + 1, l, r, opt, val);}else{change(k * 2, l, mid, opt, val);change(k * 2 + 1, mid + 1, r, opt, val);}update(k);
}long long query(long long k, long long l, long long r)
{if (l == tr[k].l && r == tr[k].r)return tr[k].sum;pushdown(k);long long mid = (tr[k].l + tr[k].r) >> 1;if (r <= mid)return query(k * 2, l, r);else if (l > mid)return query(k * 2 + 1, l, r);elsereturn (query(k * 2, l, mid) + query(k * 2 + 1, mid + 1, r)) % mod;
}void test(long long k)
{pushdown(k);printf("%lld %lld %lld %lld\n", k, tr[k].l, tr[k].r, tr[k].sum);if (tr[k].l != tr[k].r){test(k * 2);test(k * 2 + 1);}return;
}
int main()
{scanf("%lld %lld %lld", &n, &m, &mod);for (long long i = 1; i <= n; i++)scanf("%lld", &a[i]);build(1, 1, n);while (m--){long long opt;scanf("%lld", &opt);if (opt == 1){long long a, b, c;scanf("%lld %lld %lld", &a, &b, &c);change(1, a, b, opt, c);}else if (opt == 2){long long a, b, c;scanf("%lld %lld %lld", &a, &b, &c);change(1, a, b, opt, c);}else{long long a, b;scanf("%lld %lld", &a, &b);printf("%lld\n", query(1, a, b));}}return 0;
}

洛谷P3373线段树相关推荐

  1. 洛谷 P3373 线段树2

    洛谷 P3373 线段树2 mul和pls更新某区间左右子树sum的时候,别忘了回头更新这个区间的sum 只有在传递给子序列之后,父序列的lz标记才能清零.其他时候,lz标记只增不减 #include ...

  2. 洛谷P3373 线段树2(乘法加法lazytag)

    线段树模板题,含lazytag的线段树码量本身就比较大,再加入乘法标记,还要考虑先乘后加的问题,本蒟蒻一调就是几个小时. P3373 [模板]线段树 2https://www.luogu.com.cn ...

  3. 洛谷P3373线段树2

    题目描述 区间查询区间修改,非常明显的线段树模板,但乘法和加法的结合,使问题有了些小改动: problem: 该题唯一的难点就是加法和乘法的lazytag的处理,设目前区间N.s(即区间和)=x,若先 ...

  4. 洛谷 P3373 线段树模板题

    链接:https://www.luogu.com.cn/problem/P3373 题意:一个区间 三种操作 1 给lr范围内乘一个数 2 给lr范围内加一个数 3 询问lr范围内的和 啊这题真·做了 ...

  5. 洛谷3373 线段树模板

    题目详情:https://www.luogu.org/problemnew/show/P3373 这个线段树模板写的头疼(最后纠错发现一个long long没开差点一口血喷出来),思路就是在普通的求区 ...

  6. [WC2005]双面棋盘,洛谷P4121,线段树分治+可撤销并查集

    正题 这题主要是来练手的,因为没写过可撤销的并查集,大概就是把每一个格子看成一个点,然后格子直接的边有很多的出现区间,把这些出现区间和对应的颜色打到线段树上,然后用可撤销的并查集来维护就可以了. #i ...

  7. 洛谷 3373 线段树

    传送门 思路: 关键在于乘与加的先后计算关系,(x + y) * k = x * k + y * k,从这里可以看出来,把加法转化为乘法计算,取消了+与*先后顺序 pushdown时,即为乘法标记 * ...

  8. 洛谷 P3373 【模板】线段树 2 题解

    洛谷 P3373 [模板]线段树 2 题解 题面 题目链接:[戳这里](https://www.luogu.org/problemnew/show/P3373) 题目描述 输入输出格式 输入输出样例 ...

  9. 洛谷 P3373 【模板】线段树 2 解题报告

    P3373 [模板]线段树 2 题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上\(x\) 2.将某区间每一个数加上\(x\) 3.求出某区间每一个数的和 输入输出格式 ...

最新文章

  1. suffix tree
  2. bitcoin 在ubuntu上的安装指南
  3. html 响应式布局 九宫格,两种方法实现响应式九宫格布局
  4. 2022年Java项目课程目录
  5. 语义分割之Deeplabv3源码解读
  6. 云计算基础架构即服务、平台即服务、软件即服务的三种服务类型的介绍
  7. 学说话:和光合作用五道口店咖啡吧的小姑娘过招儿;推荐:《如何听如何说》 - [学说话]
  8. sql1428N错误
  9. PX4 Position_Control RC_Remoter引入
  10. 有哪些好用的思维导图软件?
  11. 当下各种关系数据库管理系统
  12. 008-我的博友不锈钢钥匙扣上的随身金属外壳可启动U盘-20190413
  13. C13-COBOL 文件处理动词
  14. 电信手机号段的归属地汇总l表
  15. Shell中的join用法
  16. 穿越小说20种恶心套路
  17. matlab保存之前的函数,MATLAB中定义函数并保存后怎么运行啊?
  18. 超市会员注册积分查询管理系统
  19. UE风格化Day16-风格化云雾材质/风格化的探讨
  20. LeetCode 反转链表(C++)

热门文章

  1. 1号线彭埠站故障已经查明 是积水导致转辙机信号不良
  2. css打印适应纸张_使用原生css+js+html实现打印A4纸张的功能页面
  3. 老徐FrankXuLei 受邀为中国东方航空上海研发中心讲授微软.NET企业开发课程
  4. html idv垂直居中,2011最新整理idv+css标准.doc
  5. HTML之如何在你的网页上放小姐姐图片
  6. Java连接Sql Server的过程及遇到的问题(极端新手向)
  7. Peekaboo—站立式会议+alpha冲刺:Day3冲刺随笔
  8. python微服务开发pdf_《微服务设计》中文完整版PDF电子书下载
  9. Power up! 这三个小时IBM都讲了些啥?
  10. fiddler抓手机APP包(安卓)