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)
根据加减法原理,,
好像只能这么解释,
先放乘法标记
再放加法标记
注意查询的时候ll和rr是不变的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define LLI long long
using namespace std;
const LLI MAXN=;
LLI read(LLI & n)
{
char p='+';LLI x=;
while(p<''||p>'')
p=getchar();
while(p>=''&&p<='')
x=x*+p-,p=getchar();
n=x;
}
LLI n,m,mod,wl,wr,wv,ans;
struct node
{
LLI l,r,w,fc,fj;
}a[MAXN];
void update(LLI k)
{
a[k].w=(a[k<<].w+a[k<<|].w)%mod;
}
void build_tree(LLI k,LLI ll,LLI rr)
{
a[k].l=ll;a[k].r=rr;
a[k].fc=;
a[k].fj=;
if(a[k].l==a[k].r)
{
read(a[k].w);
return ;
}
LLI mid=(ll+rr)/;
build_tree(k<<,ll,mid);
build_tree(k<<|,mid+,rr);
update(k);
}
void pushdown(LLI k,LLI ll,LLI rr,LLI mid)
{
a[k<<].w*=a[k].fc;a[k<<|].w*=a[k].fc;
a[k<<].w+=a[k].fj*(mid-ll+);a[k<<|].w+=a[k].fj*(rr-mid);
a[k<<].fc*=a[k].fc;a[k<<|].fc*=a[k].fc;
a[k<<].fj*=a[k].fc;a[k<<|].fj*=a[k].fc;
a[k<<].fj+=a[k].fj;a[k<<|].fj+=a[k].fj;
a[k].fc=;a[k].fj=;
a[k<<].w%=mod;a[k<<].fj%=mod;a[k<<].fc%=mod;
a[k<<|].w%=mod;a[k<<|].fj%=mod;a[k<<|].fc%=mod;
}
void interval_add(LLI k,LLI ll,LLI rr,LLI v)
{
if(a[k].l>rr||a[k].r<ll)
return ;
if(ll<=a[k].l&&rr>=a[k].r)
{
a[k].w=(a[k].w+v*(a[k].r-a[k].l+))%mod;
a[k].fj=(a[k].fj+v)%mod;
return ;
}
LLI mid=(a[k].l+a[k].r)/;
pushdown(k,a[k].l,a[k].r,mid);
//if(ll<=mid)
interval_add(k<<,ll,rr,v);
//if(rr>mid)
interval_add(k<<|,ll,rr,v);
update(k);
}
void interval_mul(LLI k,LLI ll,LLI rr,LLI v)
{
if(a[k].l>rr||a[k].r<ll)
return ;
if(ll<=a[k].l&&rr>=a[k].r)
{
a[k].w*=v%mod;
a[k].fc*=v%mod;
a[k].fj*=v%mod;
return ;
}
LLI mid=(a[k].l+a[k].r)/;
pushdown(k,a[k].l,a[k].r,mid);
//if(ll<=mid)
interval_mul(k<<,ll,rr,v);
//if(rr>mid)
interval_mul(k<<|,ll,rr,v);
update(k);
}
void interval_sum(LLI k,LLI ll,LLI rr)
{
if(a[k].l>rr||a[k].r<ll)
return ;
if(ll<=a[k].l&&rr>=a[k].r)
{
ans=(ans+a[k].w)%mod;
return ;
}
LLI mid=(a[k].l+a[k].r)/;
pushdown(k,a[k].l,a[k].r,mid);
//if(ll<=mid)
interval_sum(k<<,ll,rr);
//if(rr>mid)
interval_sum(k<<|,ll,rr);
}
int main()
{
read(n);read(m);read(mod);
build_tree(,,n);
for(LLI i=;i<=m;i++)
{
LLI p;
read(p);
if(p==)
{
read(wl);read(wr);read(wv);
interval_mul(,wl,wr,wv);
}
else if(p==)
{
read(wl);read(wr);read(wv);
interval_add(,wl,wr,wv);
}
else if(p==)
{
ans=;
read(wl);read(wr);
interval_sum(,wl,wr);
//cout<<ans%mod<<endl;
printf("%lld\n",ans%mod);
}
}
return ;
}
P3373 【模板】线段树 2 区间求和 区间乘 区间加的更多相关文章
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- hdu 1754 I Hate It (线段树功能:单点更新和区间最值)
版权声明:本文为博主原创文章.未经博主同意不得转载.vasttian https://blog.csdn.net/u012860063/article/details/32982923 转载请注明出处 ...
- 线段树&&线段树的创建线段树的查询&&单节点更新&&区间更新
目录 线段树 什么是线段树? 线段树的创建 线段树的查询 单节点更新 区间更新 未完待续 线段树 实现问题:常用于求数组区间最小值 时间复杂度:(1).建树复杂度:nlogn.(2).线段树算法复杂度 ...
- poj 1195:Mobile phones(二维线段树,矩阵求和)
Mobile phones Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 14391 Accepted: 6685 De ...
- 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 ...
- 线段树:Segment Tree(单点修改/区间修改模板) C++
线段树是非常有效的数据结构,可以快速的维护单点修改,区域修改,查询最大值,最小值等功能. 同时,它也很重要.如果有一天比赛,你卡在了一道线段树模板题目上,这就真的尴尬了.不过,随着时代的进步,题目也越 ...
- hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询
点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...
- Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间求和+点修改+区间取模
D. The Child and Sequence At the children's day, the child came to Picks's house, and messed his h ...
- 线段树(成段更新,区间求和lazy操作 )
hdu1556 Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...
- 【线段树】HDU 3397 Sequence operation 区间合并
操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters i ...
随机推荐
- html5视频播放器 一 (改写默认样式)
一个项目用到了html5视频播放器,于是就写了一个,走了很多坑,例如在chrome中加载视频出现加载异常等 先看看效果 是不是感觉换不错,以下是我播放器改写样式的布局. <!DOCTYPE ht ...
- 使用异步委托执行线程(delegate)
由于异步委托产生的线程与应用程序主线程是分开执行的,若主线程要获取异步委托线程的结果,则主线程需要等待异步委托的执行结果. BeginInvoke是Delegate类型的一个方法,它的返回类型为IAs ...
- php7.3源码编译
前置条件 autoconf:2.59+ automake:1.4+ libtool:1.4.x(除了1.4.2) re2c:0.13.4+ bison:建议1.281.35 或 1.75 依赖的库 y ...
- CentOS 5.5 介绍
转载:http://www.osyunwei.com/archives/3625.html 操作系统:CentOS 5.5主机名称:wwwIP地址:192.168.21.128网关:192.168.2 ...
- 我怎么在AD里面找到已经改名的Administrator账户?
近期有博友问我一个问题,他是一个企业里面的IT管理员,他非常苦恼.他是一个新手,之前管理员交接的时候,没有交接更改的管理员username和password.他如今不知道哪个才是系统之前内置的admi ...
- node-V8
Node是基于V8引擎的,所以我们运行Js文件不会存在问题,下面演示一下: 因为安装Vscode后,会自动添加本路径到path,所以可以用 code yes.js 来执行创建文件 Vscode是基于N ...
- asm volatile ("B .")
在开发中,我们常常会有有这种需求,就是在某段代码处開始,一步一步往下跟踪调试,有人说加个while(1)循环,事实上这个循环增加后,其后边的代码就会被优化掉,达不到我们的目的,更好的办法是在须要的地方 ...
- JavaScript 获得代码行号和脚本文件名
如果你使用的是 V8 引擎,Chrome 和 Node.js 所用的,那么你可以利用 JavaScriptStackTraceApi 来获得行号信息,有两个 API: Error.captureSta ...
- hdu 1258 Sum It Up (dfs+路径记录)
pid=1258">Sum It Up Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (J ...
- 1.Urllib2模块使用
网页抓取,就是把URL地址中指定的网络资源从网络流中读取出来,保存到本地. Urllib2介绍: urllib2 是 Python2.7 自带的模块(不需要下载,导入即可使用) urllib2 官方文 ...