大佬讲解线段树
https://blog.csdn.net/zearot/article/details/48299459
模板1题目链接
AC代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
ll sum[N<<2];
int lazy[N<<2];
ll a[N];
void Getsum(ll pos){
sum[pos]=sum[pos<<1]+sum[pos<<1|1];
return ;
}
void PushDown(ll pos,ll lnum,ll rnum){
if(lazy[pos]){
lazy[pos<<1]+=lazy[pos];
lazy[pos<<1|1]+=lazy[pos];
sum[pos<<1]+=lazy[pos]*lnum;
sum[pos<<1|1]+=lazy[pos]*rnum;
lazy[pos]=0;
}
return ;
}
void Update(ll L,ll R,ll C,ll l,ll r,ll pos){
if(l>=L && r<=R){
sum[pos]+=C*(r-l+1);
lazy[pos]+=C;
return ;
}
ll m=(l+r)>>1;
PushDown(pos,m-l+1,r-m);
if(m>=L) Update(L,R,C,l,m,pos<<1);
if(m<R) Update(L,R,C,m+1,r,pos<<1|1);
Getsum(pos);
}
void Build(ll l,ll r,ll pos){
if(l==r){
sum[pos]=a[l];
return ;
}
int m=(l+r)>>1;
Build(l,m,pos<<1);
Build(m+1,r,pos<<1|1);
Getsum(pos);
}
ll Query(ll L,ll R,ll l,ll r,ll pos){
if(r<=R && l>=L){
return sum[pos];
}
int m=(l+r)>>1;
PushDown(pos,m-l+1,r-m);
ll ans=0;
if(m>=L) ans+=Query(L,R,l,m,pos<<1);
if(m<R) ans+=Query(L,R,m+1,r,pos<<1|1);
return ans;
}
void solve(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
Build(1,n,1);
for(int i=1;i<=m;i++){
int op;
ll x,y,k;
cin>>op;
if(op==1){
cin>>x>>y>>k;
Update(x,y,k,1,n,1);
}
else{
cin>>x>>y;
cout<<Query(x,y,1,n,1)<<endl;
}
}
}
int main(){
solve();
}模板2题目链接
AC代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10;
int sum[N<<2];
int score[N];
void GetMax(int pos){
sum[pos]=max(sum[pos<<1],sum[pos<<1|1]);
}
void Build(int l,int r,int pos){
if(l==r){
sum[pos]=score[l];
return ;
}
int m=(l+r)>>1;
Build(l,m,pos<<1);
Build(m+1,r,pos<<1|1);
GetMax(pos);
}
void Update(int l,int r,int pos,int id,int grade){
if(l==r){
sum[pos]=grade;
return ;
}
int m=(l+r)>>1;
if(id<=m) Update(l,m,pos<<1,id,grade);
else Update(m+1,r,pos<<1|1,id,grade);
GetMax(pos);
}
int Query(int L,int R,int l,int r,int pos){
if(l>=L&&r<=R){
return sum[pos];
}
int m=(l+r)>>1;
int ans=0;
if(m>=L) ans=max(ans,Query(L,R,l,m,pos<<1));
if(m<R) ans=max(ans,Query(L,R,m+1,r,pos<<1|1));
return ans;
}
void solve(){
int n,m;
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;i++) scanf("%d",&score[i]);
Build(1,n,1);
while(m--){
char ch;
int l,r;
scanf(" %c%d%d",&ch,&l,&r);
if(ch=='Q'){
cout<<Query(l,r,1,n,1)<<endl;
}
else{
Update(1,n,1,l,r);
}
}
}
}
int main(){
solve();
}模板3题目链接
AC代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
ll add[N<<2],mul[N<<2],ans[N<<2],a[N];
ll mod;
void GetAns(int pos){
ans[pos]=(ans[pos<<1]+ans[pos<<1|1])%mod;
return ;
}
void Build(int l,int r,int pos){
mul[pos]=1;
add[pos]=0;
if(l==r){
ans[pos]=a[l];
return ;
}
int m=(l+r)>>1;
Build(l,m,pos<<1);
Build(m+1,r,pos<<1|1);
GetAns(pos);
}
void PushDown(int pos,int ln,int rn){//下传操作,顾名思义,对pos的子节点进行操作,标记的下传和对ans的影响
if(add[pos]!=0 || mul[pos]!=1){
ans[pos<<1]= (ans[pos<<1]*mul[pos]+add[pos]*ln)%mod;
ans[pos<<1|1]=(ans[pos<<1|1]*mul[pos]+add[pos]*rn)%mod;
add[pos<<1]= (add[pos]+add[pos<<1]*mul[pos])%mod;
add[pos<<1|1]=(add[pos]+add[pos<<1|1]*mul[pos])%mod;
mul[pos<<1]= (mul[pos<<1]*mul[pos])%mod;
mul[pos<<1|1]=(mul[pos<<1|1]*mul[pos])%mod;
mul[pos]=1;//清除标记
add[pos]=0;//同上
}
}
void Mul(int L,int R,int k,int l,int r,int pos){
if(L<=l && r<=R){
ans[pos]=ans[pos]*k%mod;
add[pos]=add[pos]*k%mod;
mul[pos]=mul[pos]*k%mod;
return ;
}
int m=(l+r)>>1;
PushDown(pos,m-l+1,r-m);
if(m>=L) Mul(L,R,k,l,m,pos<<1);
if(m<R) Mul(L,R,k,m+1,r,pos<<1|1);
GetAns(pos);//勿忘
return ;
}
void Add(int L,int R,int c,int l,int r,int pos){
if(L<=l && r<=R){
ans[pos]=(ans[pos]+c*(r-l+1))%mod;//此位置存在懒标记
add[pos]=(add[pos]+c)%mod;
return ;
}
int m=(l+r)>>1;
PushDown(pos,m-l+1,r-m);
if(m>=L) Add(L,R,c,l,m,pos<<1);
if(m<R) Add(L,R,c,m+1,r,pos<<1|1);
GetAns(pos);//勿忘
return ;
}
ll Query(int L,int R,int l,int r,int pos){
if(L<=l && r<=R){
return ans[pos];
}
int m=(l+r)>>1;
PushDown(pos,m-l+1,r-m);//勿忘
ll res=0;
if(m>=L) res=(res+Query(L,R,l,m,pos<<1))%mod;
if(m<R) res=(res+Query(L,R,m+1,r,pos<<1|1))%mod;
return res;
}
void solve(){
int n,m;
int op,x,y;
ll k,c;
cin>>n>>m>>mod;
for(int i=1;i<=n;i++) cin>>a[i];
Build(1,n,1);
while(m--){
cin>>op;
if(op==1){
cin>>x>>y>>k;
Mul(x,y,k,1,n,1);
}
else if(op==2){
cin>>x>>y>>c;
Add(x,y,c,1,n,1);
}
else{
cin>>x>>y;
cout<<Query(x,y,1,n,1)<<endl;
}
}
}
int main(){
solve();
}
//核心是PushDown、Add和Mul,理解了规定乘法的优先级大于加法,就能理解这三个函数的代码了模板1更新(20201102)
对线段树的理解更深了。
//区间查询 单点修改
#include<bits/stdc++.h>
#define ll long long
const int N=1e5+100;
const int inf=0x3f3f3f3f;
using namespace std;
struct node{
ll sum,l,r,lazy;
};
node tree[N<<2];
int x,y,n,op,m;
ll a[N],k;
void Build(int i,int l,int r)
{
tree[i].lazy=0;
tree[i].l=l;
tree[i].r=r;
if(l==r)
{
tree[i].sum=a[l];
return ;
}
int mid=(l+r)>>1;
Build(i*2,l,mid);
Build(i*2+1,mid+1,r);
tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
return ;
}
void PushDown(int i)
{
if(!tree[i].lazy) return ;
tree[2*i].sum+=tree[i].lazy*(tree[2*i].r-tree[2*i].l+1);
tree[2*i+1].sum+=tree[i].lazy*(tree[2*i+1].r-tree[2*i+1].l+1);
tree[2*i].lazy+=tree[i].lazy;
tree[2*i+1].lazy+=tree[i].lazy;
tree[i].lazy=0;
return ;
}
void Add(int i,int l,int r,ll c)
{
if(tree[i].l>=l && tree[i].r<=r)
{
tree[i].lazy+=c;
tree[i].sum+=c*(tree[i].r-tree[i].l+1);
return ;
}
PushDown(i);
if(tree[2*i].r>=l) Add(2*i,l,r,c);
if(tree[2*i+1].l<=r) Add(2*i+1,l,r,c);
tree[i].sum=tree[2*i].sum+tree[2*i+1].sum;
return ;
}
ll Query(int i,int l,int r)
{
ll res=0;
if(tree[i].l>=l && tree[i].r<=r)
return tree[i].sum;
if(tree[i].l>r || tree[i].r<l) return 0;
PushDown(i);
if(tree[2*i].r>=l) res+=Query(2*i,l,r);
if(tree[2*i+1].l<=r) res+=Query(2*i+1,l,r);
return res;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
Build(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%lld",&x,&y,&k);
Add(1,x,y,k);
}
else
{
scanf("%d%d",&x,&y);
printf("%lld\n",Query(1,x,y));
}
}
}

京公网安备 11010502036488号