洛谷——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; ...
随机推荐
- Ajax 之 DWR
DWR是开源框架,类似于hibernate.借助于DWR,开发人员无需具备专业的JavaScript知识就可以轻松实现Ajax,是Ajax更平民化. 添加jar包 dwr.jar common ...
- HttpClient-02连接管理
2.1.持久连接 两个主机建立连接的过程是很复杂的一个过程,涉及到多个数据包的交换,并且也很耗时间.Http连接需要的三次握手开销很大,这一开销对于比较小的http消息来说更大.但是如果我们直接使用已 ...
- [翻译]NUnit--Getting Started(二)
Getting Started with NUnit 如果你打算开始学习,到下载页面选择一个NUnit版本.安装页面包含了安装说明. 开始NUnit阅读Quick Start页面.验证了一个C#银行应 ...
- 深入理解JMM(Java内存模型) --(五)锁
锁的释放-获取建立的happens before 关系 锁是Java并发编程中最重要的同步机制.锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息. 下面是锁释放-获取的示例代 ...
- request.getRemoteAddr()和request.getRemoteHost()
转自:https://www.cnblogs.com/aizj/p/7593209.html request.getRemoteAddr()是获得客户端的ip地址.request.getRemoteH ...
- Unity使用外部版本控制
Using External Version Control Systems with Unity Unity offers an Asset Server add-on product for ea ...
- [App Store Connect帮助]四、添加 App 图标、App 预览和屏幕快照(3)上传 App 预览和屏幕快照
请上传至多三个 App 预览和至多十张屏幕快照.如果您的 App 在不同设备尺寸和本地化内容间都相同,仅提供所要求的最高分辨率的屏幕快照即可. 对于 iPhone,必须提供用于 5.5 英寸设备(iP ...
- GoAhead4.1.0 开发总结二(自定义使用)
环境 官方文档:https://www.embedthis.com/goahead/doc/ 源码下载: goahead-4.1.0-src.tgz 系统平台:Ubuntu 12.04.4 gcc v ...
- 【计蒜客习题】两仪剑法(gcd)
两仪剑法是武当派武功的高级功夫,且必须 2 个人配合使用威力才大.同时该剑法招数变化太快.太多.设武当弟子甲招数变化周期为 n,武当弟子乙招数变化周期为 m,两弟子同时使用该剑法,当 2 人恰好同时达 ...
- 数学 HDOJ 5301 Buildings
题目传送门 /* 题意:n*m列的矩阵,删除一个格子x,y.用矩形来填充矩阵.且矩形至少有一边是在矩阵的边缘上. 求满足条件的矩形填充方式中面积最大的矩形,要使得该最大矩形的面积最小. 分析:任何矩形 ...