题意:

操作有:区间加,区间乘,区间询问求和

思路:

设一个数为\(m*sum+a\),加就变成了\(m*sum+a+a_2\),乘就变成了\(m*m_2*sum+a*m_2\),所以我们设两个标记\(mul\)表示乘,\(add\)表示加,然后如上转化。

代码:

#include<map>
#include<set>
#include<queue>
#include<stack>
#include<ctime>
#include<cmath>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 100000 + 5;
const int INF = 0x3f3f3f3f;
const ull seed = 131;
const ll MOD = 10007;
using namespace std;
ll n, m, p;
ll sum[maxn << 2], add[maxn << 2], mul[maxn << 2];
int a[maxn];
void pushup(int rt){
sum[rt] = (sum[rt << 1] + sum[rt << 1 | 1]) % p;
}
void pushdown(int rt, int l, int r){
int m = (l + r) >> 1;
sum[rt << 1] = (sum[rt << 1] * mul[rt] + add[rt] * (m - l + 1)) % p;
sum[rt << 1 | 1] = (sum[rt << 1 | 1] * mul[rt] + add[rt] * (r - m)) % p;
add[rt << 1] = (add[rt << 1] * mul[rt] + add[rt]) % p;
add[rt << 1 | 1] = (add[rt << 1 | 1] * mul[rt] + add[rt]) % p;
mul[rt << 1] = mul[rt << 1] * mul[rt] % p;
mul[rt << 1 | 1] = mul[rt << 1 | 1] * mul[rt] % p;
add[rt] = 0;
mul[rt] = 1;
}
void build(int l, int r, int rt){
add[rt] = 0;
mul[rt] = 1;
if(l == r){
sum[rt] = a[l];
return;
}
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
pushup(rt);
}
void update(int L, int R, int l, int r, int v, int op, int rt){
if(L <= l && R >= r){
if(op == 2){
add[rt] = (add[rt] + v) % p;
sum[rt] = (sum[rt] + (r - l + 1) * v) % p;
}
else{
add[rt] = add[rt] * v % p;
mul[rt] = mul[rt] * v % p;
sum[rt] = sum[rt] * v % p;
}
return;
}
pushdown(rt, l, r);
int m = (l + r) >> 1;
if(L <= m)
update(L, R, l, m, v, op, rt << 1);
if(R > m)
update(L, R, m + 1, r, v, op, rt << 1 | 1);
pushup(rt);
}
ll query(int L, int R, int l, int r, int rt){
if(L <= l && R >= r){
return sum[rt];
}
pushdown(rt, l, r);
int m = (l + r) >> 1;
ll ret = 0;
if(L <= m)
ret += query(L, R, l, m, rt << 1);
if(R > m)
ret += query(L, R, m + 1, r, rt << 1 | 1);
return ret % p;
}
int main(){
scanf("%lld%lld%lld", &n, &m, &p);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
build(1, n, 1);
while(m--){
int op, x, y, k;
scanf("%d%d%d", &op, &x, &y);
if(op != 3) scanf("%d", &k);
if(op == 1) update(x, y, 1, n, k, 1, 1);
else if(op == 2) update(x, y, 1, n, k, 2, 1);
else printf("%lld\n", query(x, y, 1, n, 1));
}
return 0;
}

P3373 线段树2(多重标记线段树)题解的更多相关文章

  1. 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点

    题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...

  2. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  3. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  4. 主席树[可持久化线段树](hdu 2665 Kth number、SP 10628 Count on a tree、ZOJ 2112 Dynamic Rankings、codeforces 813E Army Creation、codeforces960F:Pathwalks )

    在今天三黑(恶意评分刷上去的那种)两紫的智推中,突然出现了P3834 [模板]可持久化线段树 1(主席树)就突然有了不详的预感2333 果然...然后我gg了!被大佬虐了! hdu 2665 Kth ...

  5. 【BZOJ2402】陶陶的难题II 分数规划+树链剖分+线段树+凸包

    题解: 首先分数规划是很明显的 然后在于我们如何要快速要求yi-mid*xi的最值 这个是看了题解之后才知道的 这个是斜率的一个基本方法 我们设y=mid*x+z 那么显然我们可以把(x,y)插入到一 ...

  6. 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex

    题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...

  7. 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树

    正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...

  8. ACM-ICPC 2018 焦作赛区网络预赛 E Jiu Yuan Wants to Eat (树链剖分+线段树)

    题目链接:https://nanti.jisuanke.com/t/31714 题意:给你一棵树,初始全为0,有四种操作: 1.u-v乘x    2.u-v加x   3. u-v取反  4.询问u-v ...

  9. 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)

    线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...

  10. hdu 3966(树链剖分+线段树区间更新)

    传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...

随机推荐

  1. CF625E Frog Fights

    有\(n\)只青蛙在一个长度为\(m\)的环上打架:每只青蛙有一个初始位置\(p_i\),和一个跳跃数值\(a_i\).从\(1\)号青蛙开始按序号循环行动,每次若第\(i\)只青蛙行动,则它会向前跳 ...

  2. Docker 建站小记

    一,前言 Docker 建站小记,我使用了四个镜像来搭建:nginx,certbot,mysql,gradle.欢迎访问:https://www.zzk0.top 这个网页是从 github 上找的个 ...

  3. Python干货:了解元组与列表的使用和区别

    元组是 Python 对象的集合,跟列表十分相似.下面进行简单的对比. 列表与元组 1.python中的列表list是变量,而元组tuple是常量. 列表:是使用方括号[],元组:则是使用圆括号() ...

  4. three.js cannon.js物理引擎之Heightfield

    今天郭先生说一说cannon.js物理引擎之Heightfield高度场,学过场论的朋友都知道物理学中把某个物理量在空间的一个区域内的分布称为场,高度场就是与高度相关的场,而cannon.js物理引擎 ...

  5. code-server Command ' ' not found

    由于通过一些特殊的方式登录linux用户后,全局变量不会自动加载,需要在 vscode 的 bash terminal手动读取 输入 source /etc/profile 或者vim ~/.bash ...

  6. NodeJS入门学习教程

    一.概念 1.什么是nodejs Node.js是JavaScript 运行时环境,通俗易懂的讲,Node.js是JavaScript的运行平台 Node.js既不是语言,也不是框架,它是一个平台 2 ...

  7. 使用JSONObject解析和生成json

    创建JSON 引用org.json包,推荐通过maven引用 1.直接构建 JSONObject obj = new JSONObject(); obj.put("sex", &q ...

  8. CSS选择器,属性前缀,长度单位,变形效果,过渡效果,动画效果

    CSS3选择器 ·*通配选择器 ·E标签选择器 ·E#id ID选择器 ·E.class类选择器 ·E F包含选择器,后代选择器 ·E>F子包含选择器 ·E+F相邻兄弟选择器 ·E[foo]属性 ...

  9. Jumpserver-堡垒机

    Jumpserver-堡垒机 1.基于Docker搭建Jumpserver堡垒机 1.1 下载镜像 1.2 运行镜像 1.2.1 官网步骤-Docker快速启动 1.3 浏览器访问 2.Jumpser ...

  10. vim自动添加C C++ sh文件头

    set foldenable set foldmethod=manual set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936 set ...