题目描述

如题,已知一个数列,你需要进行下面三种操作:

1.将某区间每一个数乘上x

2.将某区间每一个数加上x

3.求出某区间每一个数的和

输入格式

第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3或4个整数,表示一个操作,具体如下:

操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k

操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k

操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果

输出格式

输出包含若干行整数,即为所有操作3的结果。

输入输出样例

输入 #1 复制

5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4

输出 #1 复制

17
2

说明/提示

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=1000,M<=10000

对于100%的数据:N<=100000,M<=100000

(数据已经过加强^_^)

样例说明:

故输出应为17、2(40 mod 38=2)

///
///                            _ooOoo_
///                           o8888888o
///                           88" . "88
///                           (| -_- |)
///                           O\  =  /O
///                        ____/`---'\____
///                      .'  \\|     |//  `.
///                     /  \\|||  :  |||//  \
///                    /  _||||| -:- |||||-  \
///                    |   | \\\  -  /// |   |
///                    | \_|  ''\---/''  |   |
///                    \  .-\__  `-`  ___/-. /
///                  ___`. .'  /--.--\  `. . __
///               ."" '<  `.___\_<|>_/___.'  >'"".
///              | | :  `- \`.;`\ _ /`;.`/ - ` : | |
///              \  \ `-.   \_ __\ /__ _/   .-` /  /
///         ======`-.____`-.___\_____/___.-`____.-'======
///                            `=---='
///        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
///                      Buddha Bless, No Bug !
///
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
#define MAXN 100010
#define ll long long
#define in(a) a=read()
inline long long read()///读入数据
{long long x=0,f=1;char ch=getchar();for(; !isdigit(ch); ch=getchar())if(ch=='-')f=-1;for(; isdigit(ch); ch=getchar())x=x*10+ch-'0';return x*f;
}ll n, m, p, a[MAXN];struct node
{ll l, r, sum, mlz, plz;
} tree[4*MAXN];inline void build(long long i,long long l,long long r)///建树
{tree[i].l=l;tree[i].r=r;tree[i].mlz=1;tree[i].plz = 0;if(l==r){tree[i].sum=a[l]%p;return ;}long long mid=(l+r)>>1;build(i<<1,l,mid);///往左儿子那边的区间建树build(i<<1|1,mid+1,r);///往右儿子那边的区间建树tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;///父节点的和等于左儿子的和加右儿子的和return ;
}inline void pushdown(long long i)
{long long k1=tree[i].mlz,k2=tree[i].plz;tree[i<<1].sum=(tree[i<<1].sum*k1+k2*(tree[i<<1].r-tree[i<<1].l+1))%p;///(左儿子的值)等于(左儿子的值)*(父节点的mlz)+(父节点的plz)*(左儿子所控制的区间)tree[i<<1|1].sum=(tree[i<<1|1].sum*k1+k2*(tree[i<<1|1].r-tree[i<<1|1].l+1))%p;///(右儿子的值)等于(右儿子的值)*(父节点的mlz)+(父节点的plz)*(右儿子所控制的区间)tree[i<<1].mlz=(tree[i<<1].mlz*k1)%p;///把父节点的mlz传给左儿子tree[i<<1|1].mlz=(tree[i<<1|1].mlz*k1)%p;///把父节点的mlz传给右儿子tree[i<<1].plz=(tree[i<<1].plz*k1+k2)%p;///(左儿子的plz)等于(左儿子plz)*(父节点mlz)+(父节点plz),即为看这个点加了多少东西tree[i<<1|1].plz=(tree[i<<1|1].plz*k1+k2)%p;///(右儿子的plz)等于(右儿子plz)*(父节点mlz)+(父节点plz),即为看这个点加了多少东西tree[i].plz=0;tree[i].mlz=1;return ;
}inline void mul(long long i,long long l,long long r,long long k)
{if(tree[i].l>=l && tree[i].r<=r)///如果所查找的区间在目的区间内
    {tree[i].sum=(tree[i].sum*k)%p;///返回这个值tree[i].mlz=(tree[i].mlz*k)%p;///mlz的懒惰标记tree[i].plz=(tree[i].plz*k)%p;///plz*k表示这个区间加了那么多东西(包括了之前加的部分)return ;}pushdown(i);if(tree[i<<1].r>=l)  mul(i<<1,l,r,k);///如果要查找的区间在左儿子部分,就搜索左儿子if(tree[i<<1|1].l<=r)  mul(i<<1|1,l,r,k);///如果要查找的区间在右儿子部分,就搜索右儿子tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;///父节点sum等于两个儿子的sumreturn ;
}inline void add(long long i,long long l,long long r,long long k)
{if(tree[i].l>=l && tree[i].r<=r)///如果所查找的区间在目的区间内
    {tree[i].sum+=((tree[i].r-tree[i].l+1)*k)%p;///(该区间的和)等于(该区间的和)+(该区间所控制的元素个数)*Ktree[i].plz=(tree[i].plz+k)%p;///标记这个区间每个元素已经加了kreturn ;}pushdown(i);if(tree[i<<1].r>=l)  add(i<<1,l,r,k);///如果要查找的区间在左儿子部分,就搜索左儿子if(tree[i<<1|1].l<=r)  add(i<<1|1,l,r,k);///如果要查找的区间在右儿子部分,就搜索右儿子tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;///父节点sum等于两个儿子的sumreturn ;
}inline ll search(long long i,long long l,long long r)
{if(tree[i].r<l || tree[i].l>r) return 0;///如果这个区间不在要找的区间范围内if(tree[i].l>=l && tree[i].r<=r)///如果所查找的区间在目的区间内
    {return tree[i].sum;///直接返回这个区间的和
    }pushdown(i);long long sum=0;if(tree[i<<1].r>=l)  sum += search(i<<1,l,r);///如果要查找的区间在左儿子部分,就搜索左儿子if(tree[i<<1|1].l<=r)  sum += search(i<<1|1,l,r);///如果要查找的区间在右儿子部分,就搜索右儿子return sum %= p;
}int main()
{in(n);in(m);in(p);for(int i = 1; i <= n; i++)in(a[i]);build(1,1,n);///建树for(int i = 1; i <= m; i++){ll fl;in(fl);if(fl==1){ll x, y, k;in(x);in(y);in(k);k%=p;mul(1, x, y, k);///乘
        }if(fl==2){ll x, y, k;in(x);in(y);in(k);k%=p;add(1, x, y, k);///加
        }if(fl==3){ll x, y;in(x);in(y);printf("%lld\n", search(1,x,y));///区间查找
        }}return 0;
}

转载于:https://www.cnblogs.com/RootVount/p/11293929.html

洛谷 P3373 【模板】线段树 2(线段树区间乘、加 区间查找)相关推荐

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

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

  2. 洛谷P3373线段树

    洛谷P3373 线段树模板题,主要对懒标的处理要求比较高. 有三种操作: 区间加法 区间乘法 区间求和查询 tips:我们对一个区间进行乘k操作的时候,他之前可能存在加法lazy还没pushdown, ...

  3. 洛谷 P3373 线段树2

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

  4. 洛谷 P3373 【模板】线段树 2

    https://www.luogu.org/problem/P3373 题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每 ...

  5. 洛谷 - P1886 滑动窗口(单调队列/线段树)

    题目链接:点击查看 题目大意:给出一个由n个数构成的序列,再给出一个长度为k的窗口,这个窗口从第一个下标开始一直向后移动,每次移动一个单位,每次移动询问一次该窗口中的最大值和最小值,最后输出答案 题目 ...

  6. 【题解】洛谷P4145 花神游历各国(线段树)

    洛谷P4145:https://www.luogu.org/problemnew/show/P4145 思路 这道题的重点在于sqrt(1)=1 一个限制条件 与正常线段树不同的是区间修改为开方 那么 ...

  7. 专题·树链剖分【including 洛谷·【模板】树链剖分

    初见安~~~终于学会了树剖~~~ [兴奋]当初机房的大佬在学树剖的时候我反复强调过:"学树剖没有前途的!!!" 恩.真香. 一.重链与重儿子 所谓树剖--树链剖分,就是赋予一个链的 ...

  8. 洛谷·【模板】点分树 | 震波【including 点分树

    初见安-这里是传送门:洛谷P6329 [模板]点分树 | 震波 一.点分树 其实你会点分治的话,点分树就是把点分治时的重心提出来重新连城一棵树. 比如当前点是u,求出子树v的重心root后将root与 ...

  9. ⌈洛谷1505⌋⌈BZOJ2157⌋⌈国家集训队⌋旅游【树链剖分】

    题目链接 [洛谷] [BZOJ] 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T ...

  10. 【JZOJ3794】【洛谷P1383】高级打字机【主席树】

    题目大意: 题目链接: 洛谷:https://www.luogu.org/problemnew/show/P1383 JZOJ:https://jzoj.net/senior/#main/show/3 ...

最新文章

  1. 0525 项目回顾7.0
  2. 利用tinyproxy在Linux上搭建HTTP Proxy Server
  3. Apahce的虚拟用户认证及server-status页
  4. 安装mysql的rpm包报错_rpm包在centos6.5中安装mysql5.7初始化报错的处理办法
  5. 盐噪声和胡椒噪声的区别_为什么加一点盐对您的密码很有用(但不包括胡椒粉!)
  6. java匿名类和匿名对象及this的其他用法
  7. jvm内存模型_JVM基础:内存模型
  8. Python 函数(可变参数)
  9. 计算机开题报告参考文献,开题报告中参考文献.docx
  10. Google再曝偷偷收集用户隐私,安卓苹果用户全都中招
  11. Cesium:实现漫游飞行
  12. CSS特效(一):制作盒子荧光特效
  13. 关于利用Unity制作游戏登陆界面这件事
  14. Tampermonkey的使用
  15. 《当程序员的那些狗日日子》(八)床上等你
  16. 一个神奇的测试_神奇的心理测试:一个问题就能测试出你的情商!超准慎测
  17. 关于Android Studio项目开发的感想
  18. 固定资产管理系统如何简化固定资产管理和盘点工作?
  19. 架构:常用的三种架构模式
  20. 如何写一个简单的局域网游戏

热门文章

  1. 开源项目管理工具禅道ZenTaoPMS发布0.6 beta版本
  2. 发现一个很不错的正则表达式生成器
  3. 程序员的自我修养六可执行文件的装载与进程
  4. 前后台传值乱码问题解决
  5. ubuntu上安装nodejs
  6. 利用设计模式替代项目中的if else(转)
  7. 结构化程序设计03 - 零基础入门学习Delphi12
  8. [转]Using Angular in Visual Studio Code
  9. 后台获取(Background Fetch) - HTTP 203 Advent
  10. web前端超出两行用省略号表示