P3373 线段树2(多重标记线段树)题解
题意:
操作有:区间加,区间乘,区间询问求和
思路:
设一个数为\(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(多重标记线段树)题解的更多相关文章
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- 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 ...
- 主席树[可持久化线段树](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 ...
- 【BZOJ2402】陶陶的难题II 分数规划+树链剖分+线段树+凸包
题解: 首先分数规划是很明显的 然后在于我们如何要快速要求yi-mid*xi的最值 这个是看了题解之后才知道的 这个是斜率的一个基本方法 我们设y=mid*x+z 那么显然我们可以把(x,y)插入到一 ...
- 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex
题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...
- 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树
正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...
- 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 ...
- 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)
线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...
- hdu 3966(树链剖分+线段树区间更新)
传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...
随机推荐
- Java 8中字符串拼接新姿势:StringJoiner
介绍 StringJoiner是java.util包中的一个类,用于构造一个由分隔符分隔的字符序列(可选),并且可以从提供的前缀开始并以提供的后缀结尾.虽然这也可以在StringBuilder类的帮助 ...
- 页面切换提速30%!京东商城APP首屏耗时监控及优化实践
https://mp.weixin.qq.com/s/vIG_x1MWC33HKV1GxalVHg 原创 平台研发朱跃棕等 京东零售技术 2020-12-09 网络接口请求可以从接口结构合理性及多接口 ...
- 蓝 / 绿部署(Blue/Green) 金丝雀发布(Canary Release) 功能标记(Feature Flagging)
https://www.cnblogs.com/apanly/p/8784096.html 最终,我选择了 GraphQL 作为企业 API 网关 蓝 / 绿部署(Blue/Green) 金丝雀发布( ...
- (014)每日SQL学习:oracle下lag和lead分析函数
/*语法*/ lag(exp_str,offset,defval) over() Lead(exp_str,offset,defval) over() --exp_str要取的列 --offset取偏 ...
- 【C++小知识】#define、enum、const的含义与用法
一.#define 含义 define是宏定义,编译器不对其进行错误检查,在预编译阶段处理,没有作用域限制属于全局常量,在程序中编译器会对定义的常量名以数值进行替换,且每次替换都分配内存,此方法对于大 ...
- 序列化 serialize
Serializable 序列化 The byte stream created is platform independent. So, the object serialized on one ...
- odoo-nginx 配置之80端口
1 upstream odoo { 2 server 127.0.0.1:8069 weight=1 fail_timeout=0; 3 } 4 5 upstream odoo-im { 6 serv ...
- Java三种IO模型和LinuxIO五种IO模型
Java: https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/BIO-NIO-AIO.md https://github.co ...
- Prometheus—告警altermanger
Prometheus-告警altermanger 1.告警altermanger装配 2.告警Mysql 3.Prometheus针对nodes告警规则配置 相关内容原文地址链接: 51CTO:wfw ...
- PL/SQL 学习分享
PL SQL概述 什么是PLSQL PLSQL的特点 PLSQL的开发环境 PLSQL的工作原理 语句块重点部分 PLSQL声明命名规则 声明 命名规则 表达式和运算符 表达式的分类 运算符分类 流程 ...