洛谷——P3373 【模板】线段树 2&& B 数据结构
P3373 【模板】线段树 2
题目描述
如题,已知一个数列,你需要进行下面三种操作:
1.将某区间每一个数乘上x
2.将某区间每一个数加上x
3.求出某区间每一个数的和
线段树维护区间乘法
1.如何修改?
一个数去乘区间里的每一个数,那么这个区间的和会乘以这个数,需要乘法标记,初始化为1,乘法标记要乘以这个数,来下传到他的子树中,即更新他的子区间,当然,他的加法标记也要乘以这个数。
2.如何更新?
他子树的值=它的乘法标记*它子树的值+他子树的区间长度*它的加法标记
乘法标记更新,加法标记更新
某位大佬的线段树
#include<bits/stdc++.h>
#define N 4000000
#define LL long long
#define RE register
#define IN inline using namespace std; IN void in(LL &x){
RE char c=getchar();x=;int f=;
while(!isdigit(c)) {if(c=='-') f=-;c=getchar();}
while(isdigit(c)){x=x*+c-'';c=getchar();}
x*=f;
} /*
1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和
*/ LL n,m,X,ans,p;
struct node{
LL l,r,w,f,mul;
}e[N]; IN void build(LL k,LL l,LL r){
e[k].l=l;e[k].r=r;e[k].mul=;e[k].f=;
if(l==r){
in(e[k].w);return;
}LL mid=(l+r)/;
build(k*,l,mid);build(k*+,mid+,r);
e[k].w=(e[k*].w+e[k*+].w)%p;
} IN void down(LL k){
LL mu=e[k].mul,ll=e[k].l,rr=e[k].r,mid=(ll+rr)/;
e[k*].w=(e[k*].w*mu+e[k].f*(mid-ll+))%p;
e[k*+].w=(e[k*+].w*mu+e[k].f*(rr-mid))%p; e[k*].mul=(e[k*].mul*mu)%p;
e[k*+].mul=(e[k*+].mul*mu)%p; e[k*].f=(e[k*].f*mu+e[k].f)%p;
e[k*+].f=(e[k*+].f*mu+e[k].f)%p; e[k].f=;e[k].mul=;
} IN void mull(LL k,LL l,LL r){
LL ll=e[k].l,rr=e[k].r,mid=(ll+rr)/;
if(ll>=l&&rr<=r){
e[k].w=(e[k].w*X)%p;
e[k].mul=(e[k].mul*X)%p;
e[k].f=(e[k].f*X)%p;
return ;
}if(e[k].f!=||e[k].mul!=) down(k);
if(l<=mid) mull(k*,l,r);if(r>mid) mull(k*+,l,r);
e[k].w=(e[k*].w+e[k*+].w)%p;
} IN void change_LLerval(LL k,LL l,LL r){
LL ll=e[k].l,rr=e[k].r,mid=(ll+rr)/;
if(ll>=l&&rr<=r){
e[k].f=(e[k].f+X)%p;
e[k].w=((rr-ll+)*X+e[k].w)%p;return ;
}if(e[k].f!=||e[k].mul!=) down(k);
if(l<=mid) change_LLerval(k*,l,r);if(r>mid) change_LLerval(k*+,l,r);
e[k].w=(e[k*].w+e[k*+].w)%p;
} IN void ask_LLerval(LL k,LL l,LL r){
LL ll=e[k].l,rr=e[k].r,mid=(ll+rr)/;
if(ll>=l&&rr<=r){
ans=(e[k].w+ans)%p;return;
}if(e[k].f!=||e[k].mul!=) down(k);
if(l<=mid) ask_LLerval(k*,l,r);if(r>mid) ask_LLerval(k*+,l,r);
e[k].w=(e[k*].w+e[k*+].w)%p;
} int main()
{
in(n);in(m);in(p);
build(,,n);
while(m--){
LL tp,x,y,k;
in(tp);in(x);in(y);
if(tp!=) in(k);
if(tp==) X=k,mull(,x,y);
else if(tp==) X=k,change_LLerval(,x,y);
else{
ans=,ask_LLerval(,x,y);
printf("%d\n",ans);
}
}return ;
}
B数据结构
链接:https://www.nowcoder.com/acm/contest/200/B
来源:牛客网
qn姐姐最好了~
qn姐姐给你了一个长度为n的序列还有m次操作让你玩,
1 l r 询问区间[l,r]内的元素和
2 l r 询问区间[l,r]内的元素的平方 和
3 l r x 将区间[l,r]内的每一个元素都乘上x
4 l r x 将区间[l,r]内的每一个元素都加上x
维护区间平方和的值。其他类似吧。。
#include<bits/stdc++.h> #define N int(1e6)
#define LL long long using namespace std; void in(LL &x) {
register char c=getchar();
x=;
int f=;
while(!isdigit(c)) {
if(c=='-') f=-;
c=getchar();
}
while(isdigit(c)) {
x=x*+c-'';
c=getchar();
}
x*=f;
} struct node{
LL l,r,w1,w2,mul,ad;
}tr[N]; inline void push_up(int k){
tr[k].w1=tr[k<<].w1+tr[k<<|].w1;
tr[k].w2=tr[k<<].w2+tr[k<<|].w2;
} inline void build(LL k,LL l,LL r){
tr[k].l=l,tr[k].r=r,tr[k].mul=;
if(l==r) {
in(tr[k].w1);
tr[k].w2=tr[k].w1*tr[k].w1;
return;
}
LL mid=(l+r)>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
push_up(k);
} inline void push_down(LL k){
tr[k<<].w2=tr[k<<].w2*tr[k].mul*tr[k].mul+tr[k<<].w1**tr[k].ad+(tr[k<<].r-tr[k<<].l+)*tr[k].ad*tr[k].ad;
tr[k<<].w1=tr[k<<].w1*tr[k].mul+tr[k].ad*(tr[k<<].r-tr[k<<].l+);
tr[k<<].ad+=tr[k].ad;
tr[k<<].mul*=tr[k].mul; tr[k<<|].w2=tr[k<<|].w2*tr[k].mul*tr[k].mul+tr[k<<|].w1**tr[k].ad+(tr[k<<|].r-tr[k<<|].l+)*tr[k].ad*tr[k].ad;
tr[k<<|].w1=tr[k<<|].w1*tr[k].mul+tr[k].ad*(tr[k<<|].r-tr[k<<|].l+);
tr[k<<|].ad+=tr[k].ad;
tr[k<<|].mul*=tr[k].mul; tr[k].ad=,tr[k].mul=;
} inline void update_mul(LL k,LL L,LL R,LL w){
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>;
if(l>=L&&r<=R){
tr[k].mul*=w;
tr[k].ad*=w;
tr[k].w2=w*w*tr[k].w2;
tr[k].w1=w*tr[k].w1;
return;
}
push_down(k);
if(L<=mid) update_mul(k<<,L,R,w);
if(R>mid) update_mul(k<<|,L,R,w);
push_up(k);
} inline void update(LL k,LL L,LL R,LL w){
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>;
if(l>=L&&r<=R){
tr[k].w2+=tr[k].w1**w+(r-l+)*w*w;
tr[k].w1+=w*(r-l+);
tr[k].ad+=w;
return;
}
push_down(k);
if(L<=mid) update(k<<,L,R,w);
if(R>mid) update(k<<|,L,R,w);
push_up(k);
} LL query1(LL k,LL L,LL R){
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>;
if(l>=L&&r<=R) return tr[k].w1;
push_down(k);
LL an=;
if(L<=mid) an+=query1(k<<,L,R);
if(R>mid) an+=query1(k<<|,L,R);
push_up(k);
return an;
} LL query2(LL k,LL L,LL R){
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>;
if(l>=L&&r<=R) return tr[k].w2;
push_down(k);
LL an=;
if(L<=mid) an+=query2(k<<,L,R);
if(R>mid) an+=query2(k<<|,L,R);
push_up(k);
return an;
} LL n,m; int main()
{
in(n),in(m);
build(,,n);
for(LL opt,l,r,w,i=;i<=m;i++){
in(opt),in(l),in(r);
if(opt==){
printf("%lld\n",query1(,l,r));
}
if(opt==){
printf("%lld\n",query2(,l,r));
}
if(opt==){
in(w);
update_mul(,l,r,w);
}
if(opt==){
in(w);
update(,l,r,w);
}
}
return ;
}
洛谷——P3373 【模板】线段树 2&& B 数据结构的更多相关文章
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 线段树_区间加乘(洛谷P3373模板)
题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 输入格式: 第一行包含三个整数N.M.P,分别表示该数列数字 ...
- 洛谷 - P1198 - 最大数 - 线段树
https://www.luogu.org/problemnew/show/P1198 要问区间最大值,肯定是要用线段树的,不能用树状数组.(因为没有逆元?但是题目求的是最后一段,可以改成类似前缀和啊 ...
- 洛谷 P2391 白雪皑皑 线段树+优化
题目描述: 现在有 \(N\) 片雪花排成一列. Pty 要对雪花进行$ M $次染色操作,第 \(i\)次染色操作中,把\((i*p+q)%N+1\) 片雪花和第\((i*q+p)%N+1\)片雪花 ...
- 【洛谷】【线段树】P1471 方差
[题目背景:] 滚粗了的HansBug在收拾旧数学书,然而他发现了什么奇妙的东西. [题目描述:] 蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的平均数和方差 ...
- 【洛谷】【线段树】P1047 校门外的树
[题目描述:] 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,……,L ...
- 【洛谷】【线段树】P1886 滑动窗口
[题目描述:] 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. [输入格式:] 输入一共 ...
- 【洛谷】【线段树】P3353 在你窗外闪耀的星星
[题目描述:] /* 飞逝的的时光不会模糊我对你的记忆.难以相信从我第一次见到你以来已经过去了3年.我仍然还生动地记得,3年前,在美丽的集美中学,从我看到你微笑着走出教室,你将头向后仰,柔和的晚霞照耀 ...
- 洛谷P5280 [ZJOI2019]线段树
https://www.luogu.org/problemnew/show/P5280 省选的时候后一半时间开这题,想了接近两个小时的各种假做法,之后想的做法已经接近正解了,但是有一些细节问题理不 ...
- 洛谷P3374(线段树)(询问区间和,支持单点修改)
洛谷P3374 //询问区间和,支持单点修改 #include <cstdio> using namespace std; ; struct treetype { int l,r,sum; ...
随机推荐
- https://security.stackexchange.com/questions/68405/what-is-tmunblock-cgi-and-can-it-be-exploited-by-shellshock-linux-apache-w
hndUnblock.cgi Line #1124 : 187.38.233.45 - - [15/Jan/2018:21:36:45 +0800] "GET /hndUnblock.c ...
- NTFS文件系统的单个文件最大到底有多大?
于NTFS文件系统的单个文件最大到底有多大? 闲来无事突然想到这个问题,到网上搜索了一下也没有一个固定的解释. 于是到微软官方知识库去寻找答案: 注意:基础硬件限制可能会对任何文件系统施加额外的分区大 ...
- luogu 3953 逛公园
noip2017 D1T3 逛公园 某zz选手看到数据范围直接就最短路计数了,结果写错了爆零 题目大意: N个点M条边构成的有向图,且没有自环和重边.其中1号点是起点,N号点是公园的终点,每条边有一个 ...
- Vue.js 项目接口管理
在vue开发中,会涉及到很多接口的处理,当项目足够大时,就需要定义规范统一的接口,如何定义呢? 本文使用vue-cli生成的项目举例. 第一步.在src目录下新建一个文件夹http,在http目录下建 ...
- bzoj 1571: [Usaco2009 Open]滑雪课Ski【dp】
参考:https://blog.csdn.net/cgh_andy/article/details/52506738 没有get到什么重点的dp--做的莫名其妙 注意滑雪一个坡可以滑很多次 设f[i] ...
- [Qt Creator 快速入门] 第4章 布局管理
第3章讲述了一些窗口部件,当时往界面上拖放部件时都是随意放置的,这对于学习部件的使用没有太大的影响,但是,对于一个完善的软件,布局管理却是必不可少的. 无论是想要界面中部件有一个很整齐的排列,还是想要 ...
- 51nod 1029 大数除法
1029 大数除法 基准时间限制:4 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 收藏 关注 给出2个大整数A,B,计算A / B和A Mod B的结果. Input 第1 ...
- 同余模定理 HDOJ 5373 The shortest problem
题目传送门 /* 题意:题目讲的很清楚:When n=123 and t=3 then we can get 123->1236->123612->12361215.要求t次操作后, ...
- 转发:吐血总结,彻底明白 python3 编码原理
吐血总结,彻底明白 python3 编码原理 写的不错,转发学习一下,侵删.. 原文地址https://zhuanlan.zhihu.com/p/40834093 防止原文看不到了 这里粘贴复制一下: ...
- MySql 同表复制数据 可以改变数据
Mysql语法: INSERT INTO 表名 (字段) SELECT 字段 FROM 表名 WHERE 条件: 如果要修改其中某一个字段,在查询语句中:x(要改变的值) as 字段名. eg: IN ...