luogu P3373 【模板】线段树 2
题目描述
如题,已知一个数列,你需要进行下面两种操作:
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的结果。
输入输出样例
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
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)
需要越来越习惯lazy-tag的使用才行啊
tag1表示乘,tag2表示加
线段树的写法真是各有各的风格 大雾
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; typedef long long ll; inline int read(){
char ch;
int re=;
bool flag=;
while((ch=getchar())!='-'&&(ch<''||ch>''));
ch=='-'?flag=:re=ch-'';
while((ch=getchar())>=''&&ch<='') re=re*+ch-'';
return flag?-re:re;
} struct segment{
int l,r;
ll sum,tag1,tag2;
segment(){
sum=;
tag1=;
tag2=;
}
}; const int maxn=; int cnt,n,m;
ll mod;
segment tre[maxn<<];
int data[maxn]; inline void push_up(int x){
tre[x].sum=(tre[x<<].sum+tre[x<<|].sum)%mod;
} void build(int x,int l,int r){
tre[x].l=l; tre[x].r=r;
if(l==r){
tre[x].sum=data[l];
return;
}
int mid=(l+r)>>;
build(x<<,l,mid); build(x<<|,mid+,r);
push_up(x);
} void init(){
n=read(); m=read(); mod=read();
for(int i=;i<=n;i++) data[i]=read();
build(,,n);
} inline void push_down(int x){
int lson=x<<,rson=lson|; if(tre[x].tag1!=){
tre[lson].tag1=(tre[lson].tag1*tre[x].tag1)%mod;
tre[rson].tag1=(tre[rson].tag1*tre[x].tag1)%mod;
tre[lson].tag2=(tre[lson].tag2*tre[x].tag1)%mod;
tre[rson].tag2=(tre[rson].tag2*tre[x].tag1)%mod;
tre[lson].sum=(tre[lson].sum*tre[x].tag1)%mod;
tre[rson].sum=(tre[rson].sum*tre[x].tag1)%mod;
tre[x].tag1=;
} if(tre[x].tag2){
tre[lson].tag2=(tre[lson].tag2+tre[x].tag2)%mod;
tre[lson].sum=(tre[lson].sum+tre[x].tag2*(tre[lson].r-tre[lson].l+))%mod;
tre[rson].tag2=(tre[rson].tag2+tre[x].tag2)%mod;
tre[rson].sum=(tre[rson].sum+tre[x].tag2*(tre[rson].r-tre[rson].l+))%mod;
tre[x].tag2=;
}
} void update_add(int x,int L,int R,int c){
if(L<=tre[x].l&&tre[x].r<=R){
tre[x].tag2=(tre[x].tag2+c)%mod;
tre[x].sum=(tre[x].sum+c*(tre[x].r-tre[x].l+))%mod;
return;
} int mid=(tre[x].l+tre[x].r)>>;
if(tre[x].tag1!=||tre[x].tag2) push_down(x);
if(R<=mid) update_add(x<<,L,R,c);
else if(L>mid) update_add(x<<|,L,R,c);
else{ update_add(x<<,L,mid,c); update_add(x<<|,mid+,R,c); }
push_up(x);
} void update_mul(int x,int L,int R,int c){
if(L<=tre[x].l&&tre[x].r<=R){
tre[x].tag1=(tre[x].tag1*c)%mod;
tre[x].tag2=(tre[x].tag2*c)%mod;
tre[x].sum=(tre[x].sum*c)%mod;
return;
} int mid=(tre[x].l+tre[x].r)>>;
if(tre[x].tag1!=||tre[x].tag2) push_down(x);
if(R<=mid) update_mul(x<<,L,R,c);
else if(L>mid) update_mul(x<<|,L,R,c);
else{ update_mul(x<<,L,mid,c); update_mul(x<<|,mid+,R,c); }
push_up(x);
} ll query_sum(int x,int L,int R){
if(L<=tre[x].l&&tre[x].r<=R){
return tre[x].sum;
}
if(tre[x].tag1!=||tre[x].tag2) push_down(x);
int mid=(tre[x].l+tre[x].r)>>;
if(R<=mid) return query_sum(x<<,L,R);
if(L>mid) return query_sum(x<<|,L,R);
return (query_sum(x<<,L,mid)+query_sum(x<<|,mid+,R))%mod;
} void solve(){
int opt,L,R,c;
for(int i=;i<m;i++){
opt=read();
switch(opt){
case :{
L=read(); R=read(); c=read();
update_mul(,L,R,c);
break;
}
case :{
L=read(); R=read(); c=read();
update_add(,L,R,c);
break;
}
case :{
L=read(); R=read();
printf("%lld\n",query_sum(,L,R));
break;
}
}
}
} int main(){
//freopen("temp.in","r",stdin);
init();
solve();
return ;
}
她的话不多但笑起来是那么平静优雅
她柔弱的眼神里装的是什么 是思念的忧伤
luogu P3373 【模板】线段树 2的更多相关文章
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- hdu 1754 I Hate It (模板线段树)
http://acm.hdu.edu.cn/showproblem.php?pid=1754 I Hate It Time Limit: 9000/3000 MS (Java/Others) M ...
- hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询
点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...
- 【线段树】【P3372】模板-线段树
百度百科 Definition&Solution 线段树是一种log级别的树形结构,可以处理区间修改以及区间查询问题.期望情况下,复杂度为O(nlogn). 核心思想见百度百科,线段树即将每个 ...
- [Luogu] 可持久化线段树 1(主席树)
https://www.luogu.org/problemnew/show/P3834 #include<cstdio> #include<iostream> #include ...
- 算法模板——线段树6(二维线段树:区域加法+区域求和)(求助phile)
实现功能——对于一个N×M的方格,1:输入一个区域,将此区域全部值作加法:2:输入一个区域,求此区域全部值的和 其实和一维线段树同理,只是不知道为什么速度比想象的慢那么多,求解释...@acphile ...
- Luogu P5280 [ZJOI2019]线段树
送我退役的神题,但不得不说是ZJOIDay1最可做的一题了 先说一下考场的ZZ想法以及出来后YY的优化版吧 首先发现每次操作其实就是统计出增加的节点个数(原来的不会消失) 所以我们只要统计出线段树上每 ...
- luogu 1712 区间(线段树+尺取法)
题意:给出n个区间,求选择一些区间,使得一个点被覆盖的次数超过m次,最小的花费.花费指的是选择的区间中最大长度减去最小长度. 坐标值这么大,n比较小,显然需要离散化,需要一个技巧,把区间转化为半开半闭 ...
- Luogu P3960 列队 线段树
题面 线段树入门题. 我们考虑线段树来维护这个矩阵. 首先我们先定n+1棵线段树前n棵维护每行前m-1个同学中没有离队过的同学,还有一棵维护第m列中没有离队过的同学.再定n+1棵线段树前n棵线段树维护 ...
- Luogu P1471 方差 线段树
那是上上周...也是重构了四遍...后来GG了...今天又拾起,搞了搞终于过了... 好吧就是个线段树,公式懒得推了https://www.cnblogs.com/Jackpei/p/10693561 ...
随机推荐
- vue-cli webpack在node环境下安装使用
第一步,需要下载并安装node.js以及他的npm组件: 第二步,用node -v;npm -v来测试node.js以及npm是否安装成功(建议用GIT命令行工具,因为GIT是linux系统),如果显 ...
- 写了一个Mac快速设置、打开和关闭Web代理的Shell命令
缘由(痛点) 每次在Mac上设置Web代理,都需要点开"系统偏好设置 -- 网络 -- 高级 -- 代理",然后分别设置Web代理(HTTP)和安全Web代理(HTTPS),设置完 ...
- java基础(二章)
java基础(二章) 一,变量 1.变量是内存中的一个标识符号,用于存储数据 2.变量命名规则 l 必须以字母.下划线 _ .美元符号 $ 开头 l 变量中,可以包括数字 l 变量中,不能出现特 ...
- 关于redis内部的数据结构
最大感受,无论从设计还是源码,Redis都尽量做到简单,其中运用到的原理也通俗易懂.特别是源码,简洁易读,真正做到clean and clear, 这篇文章以unstable分支的源码为基准,先从大体 ...
- 判断客户端使用的是安卓还是苹果,然后加载对应的css文件
<script type="text/javascript" charset="utf-8"> var browser = { versions: ...
- Java基础——继承
学习Java继承之前,我们想回忆一下Java面向对象需要特别注意的几个关键点. 面向对象是将复杂的事情简单化了,它通过封装的方式使得代码的重用性更高和安全性更强.平时我们要学会用面向对象的方式去思考, ...
- ionic2 tabs使用自定义图标
在ionic2中图标是通过类添加的 比如说 tabIcon="homeImg" 在页面中研究可以看到在ios上有一个类是 .ion-ios-homeImg:before 所以我 ...
- 一个编程菜鸟的进阶之路(C/C++)
学编程是一条不归路,但我义无反顾.只能往前冲,知道这个过程是痛苦的,所以我开通这个博客,记录自己在编程中遇到的问题和心得,一是希望可以帮助跟我一样遇到同样问题的人,二是把这作为对自己的勉励及回忆:
- nodejs+websocket制作聊天室视频教程
本套教程主要讲解了node平台的安装,node初级知识.node 服务器端程序响应http请求,通过npm安装第三方包,websocket即时通讯.聊天页面界面制作.拖动原理.拖动效果.遮罩效果.定位 ...
- 理解容器之间的连通性 - 每天5分钟玩转 Docker 容器技术(34)
通过前面小节的实践,当前 docker host 的网络拓扑结构如下图所示,今天我们将讨论这几个容器之间的连通性. 两个 busybox 容器都挂在 my_net2 上,应该能够互通,我们验证一下: ...