【原创】洛谷 LUOGU P3373 【模板】线段树2
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)
// LUOGU 3373 【模板】线段树2
// 2017.7.20 20:52
#include<bits/stdc++.h>
#define INF 0x3fffffff
#define MAXN 100000
#define MAXT MAXN*4
using namespace std;
typedef long long ll;
int N,M,topt=;
ll P,a[MAXN+];
struct sgt_node{
int lc,rc;
ll sum,pls,mul;
sgt_node(){pls=,mul=INF;}
}sgt[MAXT+];
int getint(){
char ch='*';
while(!isdigit(ch=getchar()));
int num=ch-'';
while(isdigit(ch=getchar()))num=num*+ch-'';
return num;
}
ll getll(){
char ch='*';
while(!isdigit(ch=getchar()));
ll num=ch-'';
while(isdigit(ch=getchar()))num=num*+ch-'';
return num;
}
#define lch sgt[now].lc
#define rch sgt[now].rc
#define smid ((l+r)>>1)
void update(int now){
sgt[now].sum=(sgt[lch].sum+sgt[rch].sum)%P;
}
void set_mul(int now,ll v){
sgt[now].sum=(sgt[now].sum*v)%P;
if(sgt[now].mul==INF)sgt[now].mul=v%P;
else sgt[now].mul=(sgt[now].mul*v)%P; // 必须为乘法!!!
sgt[now].pls=(sgt[now].pls*v)%P;
}
void set_pls(int now,int l,int r,ll v){
sgt[now].sum=(sgt[now].sum+v*(r-l+))%P;
sgt[now].pls=(sgt[now].pls+v)%P;
}
void push_down(int now,int l,int r){
if(sgt[now].mul!=INF){
set_mul(lch,sgt[now].mul);
set_mul(rch,sgt[now].mul);
sgt[now].mul=INF;
}
if(sgt[now].pls){
set_pls(lch,l,smid,sgt[now].pls);
set_pls(rch,smid+,r,sgt[now].pls);
sgt[now].pls=;
}
}
void Build_sgt(int &now,int l,int r){
now=++topt;
if(l==r){
sgt[now].sum=a[l];
return;
}
Build_sgt(lch,l,smid);
Build_sgt(rch,smid+,r);
update(now);
}
ll Query_sgt(int now,int l,int r,int qx,int qy){
if(l==qx&&r==qy)return sgt[now].sum;
push_down(now,l,r);
if(qy<=smid)return Query_sgt(lch,l,smid,qx,qy);
if(qx>smid)return Query_sgt(rch,smid+,r,qx,qy);
return Query_sgt(lch,l,smid,qx,smid)+Query_sgt(rch,smid+,r,smid+,qy);
}
void Region_mul(int now,int l,int r,int x,int y,ll v){
if(l==x&&r==y){
set_mul(now,v);
return;
}
push_down(now,l,r);
if(y<=smid)Region_mul(lch,l,smid,x,y,v);
else if(x>smid)Region_mul(rch,smid+,r,x,y,v);
else{
Region_mul(lch,l,smid,x,smid,v);
Region_mul(rch,smid+,r,smid+,y,v);
}
update(now);
}
void Region_pls(int now,int l,int r,int x,int y,ll v){
if(l==x&&r==y){
set_pls(now,l,r,v);
return;
}
push_down(now,l,r);
if(y<=smid)Region_pls(lch,l,smid,x,y,v);
else if(x>smid)Region_pls(rch,smid+,r,x,y,v);
else{
Region_pls(lch,l,smid,x,smid,v);
Region_pls(rch,smid+,r,smid+,y,v);
}
update(now);
}
int main(){
N=getint(),M=getint(),P=getll();
for(int i=;i<=N;i++)
a[i]=getll();
int root=;
Build_sgt(root,,N);
int op,x,y;
ll k;
for(int i=;i<=M;i++){
op=getint();
switch(op){
case :
x=getint(),y=getint(),k=getll();
Region_mul(,,N,x,y,k);
break;
case :
x=getint(),y=getint(),k=getll();
Region_pls(,,N,x,y,k);
break;
case :
x=getint(),y=getint();
printf("%lld\n",Query_sgt(,,N,x,y)%P);
break;
}
}
return ;
}
【原创】洛谷 LUOGU P3373 【模板】线段树2的更多相关文章
- 【洛谷 p3372】模板-线段树 1(数据结构--线段树)
题目:已知一个数列,你需要进行下面两种操作:1.将某区间每一个数加上x:2.求出某区间每一个数的和. 解法:如题,模版题.需要加上 lazy 标记,也就是我的 upd.lazy 标记的思路就是对一个结 ...
- 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释
P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...
- 洛谷p3384【模板】树链剖分题解
洛谷p3384 [模板]树链剖分错误记录 首先感谢\(lfd\)在课上调了出来\(Orz\) \(1\).以后少写全局变量 \(2\).线段树递归的时候最好把左右区间一起传 \(3\).写\(dfs\ ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 洛谷P3834 可持久化线段树(主席树)模板
题目:https://www.luogu.org/problemnew/show/P3834 无法忍受了,我要写主席树! 解决区间第 k 大查询问题,可以用主席树,像前缀和一样建立 n 棵前缀区间的权 ...
- 洛谷 P3384 【模板】树链剖分
树链剖分 将一棵树的每个节点到它所有子节点中子树和(所包含的点的个数)最大的那个子节点的这条边标记为"重边". 将其他的边标记为"轻边". 若果一个非根节点的子 ...
- 洛谷题解P4314CPU监控--线段树
题目链接 https://www.luogu.org/problemnew/show/P4314 https://www.lydsy.com/JudgeOnline/problem.php?id=30 ...
- 【BZOJ】1012: [JSOI2008]最大数maxnumber /【洛谷】1198(线段树)
Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插 ...
- 『题解』洛谷P3384 【模板】树链剖分
Problem Portal Portal1: Luogu Description 如题,已知一棵包含\(N\)个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作\(1\): ...
随机推荐
- selenium登录4399
from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from seleni ...
- WPF入门(1)——DataContext
在WPF中,应用程序有两层:UI层和Data层.这里新建一个项目说明哪些是UI层,哪些是数据层. UI层很明显,就是用户看到的界面.但是数据层并不是下图所示: 上图中是UI层view的后台代码.当然, ...
- Delphi cxpagecontrol融合窗体
功能说明: 一.在需要融合的每个窗体加一句 initialization RegisterClasses([TFrmDataDict]); //类名 二.cxpagecontrol融合窗体,在调用时 ...
- ggpubr进行“paper”组图合并,也许比PS,AI更简单
本文转载自微信公众号 “生信补给站”,https://mp.weixin.qq.com/s/41iKTulTwGcY-dHtqqSnLA 多个图形进行组图展示,可以既展示一个“事情”的多个角度,也可以 ...
- codeforce E - Minimal Labels+hdu 4857
两个题目的意思差不多 都是希望得出的拓扑序如果有多种 要求输出字典序小的情况 这里引用一个大佬的博客 关于为什么不能直接建图然后用小根堆解决这个问题(http://blog.csdn.net/rgno ...
- VBA精彩代码分享-2
VBA开发中经常需要提示消息框,如果不关闭程序就会暂时中断,这里分享下VBA如何实现消息框的自动关闭,总共有三种方法: 第一种方法 Public Declare Function MsgBoxTime ...
- Lua的栈及基本栈操作
Lua的栈及基本栈操作 https://blog.csdn.net/mydriverc2/article/details/51134737 https://blog.csdn.net/mydriver ...
- Git详细操作
Git详细操作 一.本地配置 1公钥钥配置 1.参考帮助文档:https://gitee.com/help/ 仓库管理 =公钥管理 =生成/添加SSH公钥 ssh-keygen -t rsa -C & ...
- luogu题解 P4092 【[HEOI2016/TJOI2016]树】树链剖分
题目链接: https://www.luogu.org/problemnew/show/P4092 瞎扯--\(O(Q \log^3 N)\)解法 这道先yy出了一个\(O(Q \log^3 N)\) ...
- BigDecimal与Long、int之间的相互转换
//bigDecimal 转换成 Long类型 public static Long bigDecimalToLong(BigDecimal b){ BigDecimal c = new BigDec ...