线段树基础

线段树

单点查询 区间查询 单点修改 区间修改 预处理 特点
数组 O(1) O(n) O(1) O(n)
前缀和 O(1) O(1) O(n) O(n)
差分 O(n) O(n) O(1) O(1)
树状数组 O(logn) O(logn) O(logn) 快速询问区间和
ST表 O(1) O(nlogn) 多次询问区间最值
线段树(数组开4*n) O(logn) O(logn) O(logn) O(n)总:O(mlogn) 区间加(乘)法
链表 删除O(1) O(1)查前驱后继

单点修改,区间求和

位运算建树

#include<iostream>
#include<cstdio>
#define re register int
#define ls (p<<1)
#define rs (p<<1|1)
using namespace std;
const int MAXN=4e5+5;
long long val[MAXN],lazy[MAXN];
int n,m,a[MAXN],root;
inline int read(){
	int x=0;int f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}

inline void pushup(int p){
	val[p]=val[ls]+val[rs];
}

inline void pushdown(int p,int l,int r){
	if(!lazy[p]) return;
	lazy[ls]+=lazy[p];
	lazy[rs]+=lazy[p];
	int mid=(l+r)>>1;
	val[ls]+=lazy[p]*(mid-l+1);
	val[rs]+=lazy[p]*(r-mid);
	lazy[p]=0;
}

void build(int l,int r,int p){
	if(l==r){
		val[p]=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,ls);
	build(mid+1,r,rs);
	pushup(p);
}

void modify(int l,int r,int ql,int qr,int p,long long add){
	if(ql<=l&&qr>=r){
		val[p]+=add*(r-l+1);
		lazy[p]+=add;
		return;
	}
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	if(ql<=mid) modify(l,mid,ql,qr,ls,add);
	if(qr>mid) modify(mid+1,r,ql,qr,rs,add);
	pushup(p);
}

long long query(int l,int r,int ql,int qr,int p){
	if(ql<=l&&qr>=r) return val[p];
	pushdown(p,l,r);
	long long ans=0;
	int mid=(l+r)>>1;
	if(ql<=mid) ans+=query(l,mid,ql,qr,ls);
	if(qr>mid) ans+=query(mid+1,r,ql,qr,rs);
	return ans;	
}

int main(){
	n=read(),m=read();
	for(re i=1;i<=n;i++) a[i]=read();
	build(1,n,1);
	for(re i=1;i<=m;i++) {
		int t=read(),x=read(),y=read(),z;
		if(t==1) {
			z=read();
			modify(1,n,x,y,1,z);
		} else {
			printf("%lld\n",query(1,n,x,y,1));
		}
	} 
	return 0;
}

动态开点

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
typedef long long ll;
ll val[N],lazy[N];
int ls[N],rs[N];
int n,m,root,cnt,tree_cnt,a[N];
inline void pushup(int p){
	val[p]=val[ls[p]]+val[rs[p]];
}
inline void pushdown(int p,int l,int r){
	if(!lazy[p])return;
	lazy[ls[p]]+=lazy[p];
	lazy[rs[p]]+=lazy[p];
	int mid=(l+r)>>1;
	val[ls[p]]+=lazy[p]*(mid-l+1);
	val[rs[p]]+=lazy[p]*(r-mid);
	lazy[p]=0;
}
inline void build(int &p,int l,int r){
	p=++tree_cnt;
	if(l==r){
		val[p]=a[l];return;
	}
	int mid=(l+r)>>1;
	build(ls[p],l,mid);
	build(rs[p],mid+1,r);
	pushup(p);
}
void modify(int p,ll v,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr){
		val[p]+=v*(r-l+1);
		lazy[p]+=v;
		return;
	}
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	if(ql<=mid) modify(ls[p],v,l,mid,ql,qr);
	if(qr>mid) modify(rs[p],v,mid+1,r,ql,qr);
	pushup(p);
}
ll query(int p,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr)return val[p];
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	ll ans=0;
	if(ql<=mid) ans+=query(ls[p],l,mid,ql,qr);
	if(qr>mid) ans+=query(rs[p],mid+1,r,ql,qr);
	return ans;
}
int main(){
	 scanf("%d%d",&n,&m);
     for(int i=1;i<=n;i++)
         scanf("%d",&a[i]);
     int root=1;
     build(root,1,n);
     for(int i=1,t,x,y,z;i<=m;i++){
     	 scanf("%d%d%d",&t,&x,&y);
		 if(t==1){
             scanf("%d",&z);
             modify(1,z,1,n,x,y);
         }
         else  printf("%lld\n",query(1,1,n,x,y));
     } 
	return 0;
}

区间乘法,区间加,区间求和

#include<iostream>
#include<cstdio>
#include<cctype>
#define re register int
using namespace std;
const int MAXN=4e5+5;
long long val[MAXN],lazy1[MAXN],lazy2[MAXN];//1* 2+
int n,m,tree_cnt,ls[MAXN],rs[MAXN],a[MAXN],root,p;
inline int read()
{
	int x=0;int f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}

inline void pushup(int cur){
	val[cur]=(val[ls[cur]]+val[rs[cur]])%p;
}

inline void pushdown(int cur,int l,int r){
	if(lazy1[cur]==1&&!lazy2[cur]) return;
	val[ls[cur]]=(lazy1[cur]*val[ls[cur]])%p;
	val[rs[cur]]=(lazy1[cur]*val[rs[cur]])%p;
	lazy1[ls[cur]]=(lazy1[ls[cur]]*lazy1[cur])%p;
	lazy1[rs[cur]]=(lazy1[rs[cur]]*lazy1[cur])%p;
	lazy2[ls[cur]]=(lazy2[ls[cur]]*lazy1[cur])%p;
	lazy2[rs[cur]]=(lazy2[rs[cur]]*lazy1[cur])%p;
	lazy2[ls[cur]]+=lazy2[cur];
	lazy2[rs[cur]]+=lazy2[cur];
	lazy1[ls[cur]]%=p;
	lazy1[rs[cur]]%=p;
	lazy2[ls[cur]]%=p;
	lazy2[rs[cur]]%=p;
	int mid=(l+r)>>1;
	val[ls[cur]]+=lazy2[cur]*(mid-l+1);
	val[rs[cur]]+=lazy2[cur]*(r-mid);
	lazy1[cur]=1;lazy2[cur]=0;
}

void build(int l,int r,int &cur){
	cur=++tree_cnt;
	if(l==r){
		val[cur]=a[l]%p;
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,ls[cur]);
	build(mid+1,r,rs[cur]);
	pushup(cur);
}

void modify1(int l,int r,int ql,int qr,int cur,long long add){
	if(ql<=l&&qr>=r){
		val[cur]=(val[cur]*add)%p;
		lazy1[cur]=(add*lazy1[cur])%p;
		lazy2[cur]=(add*lazy2[cur])%p;
		return;
	}
	pushdown(cur,l,r);
	int mid=(l+r)>>1;
	if(ql<=mid) modify1(l,mid,ql,qr,ls[cur],add);
	if(qr>mid) modify1(mid+1,r,ql,qr,rs[cur],add);
	pushup(cur);
}

void modify2(int l,int r,int ql,int qr,int cur,long long add){
	if(ql<=l&&qr>=r){
		val[cur]=(add*(r-l+1)+val[cur])%p;
		lazy2[cur]=(lazy2[cur]+add)%p;
		return;
	}
	pushdown(cur,l,r);
	int mid=(l+r)>>1;
	if(ql<=mid) modify2(l,mid,ql,qr,ls[cur],add);
	if(qr>mid) modify2(mid+1,r,ql,qr,rs[cur],add);
	pushup(cur);
}

long long query(int l,int r,int ql,int qr,int cur){
	if(ql<=l&&qr>=r) return val[cur]%p;
	pushdown(cur,l,r);
	long long ans=0;
	int mid=(l+r)>>1;
	if(ql<=mid) ans+=query(l,mid,ql,qr,ls[cur]);
	if(qr>mid) ans+=query(mid+1,r,ql,qr,rs[cur]);
	return ans%p;	
}

signed main(){
	n=read(),m=read(),p=read();
	for(re i=1;i<=n;i++)
		a[i]=read();
	for(re i=1;i<=n*4+3;i++) lazy1[i]=1;
	int root=1;	
	build(1,n,root);
	for(re i=1;i<=m;i++){
		int t=read(),x=read(),y=read(),z;
		if(t==1){
			z=read();
			modify1(1,n,x,y,1,z);
		}
		else if(t==2){
			z=read();
			modify2(1,n,x,y,1,z);
		}
		else{
			printf("%lld\n",query(1,n,x,y,1));
		}
	} 
	return 0;
}

区间加,区间替换,区间最值,区间求和

板子

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=1000001;
#define ls p<<1
#define rs p<<1|1
int n,m,a[N]; 
struct tree{
	int l,r,sum,mi,mx,atag,ctag;
}t[N*4];
inline void pushup(int p){
	t[p].sum=t[ls].sum+t[rs].sum;
	t[p].mx=max(t[ls].mx,t[rs].mx);
	t[p].mi=min(t[ls].mi,t[rs].mi);
}
void build(int l,int r,int p){
	t[p].ctag=-1;t[p].l=l;t[p].r=r;
	if(l==r){
		scanf("%d",&t[p].sum);
		t[p].mi=t[p].mx=t[p].sum;return;
	}
	int mid=(l+r)>>1;
	build(l,mid,ls);
	build(mid+1,r,rs);
	pushup(p);
}
inline void pushdown(int p){
	int c=t[p].ctag,a=t[p].atag,x=t[p].r-t[p].l+1;
	if(c!=-1){
		t[ls].ctag=t[rs].ctag=c;
		t[ls].atag=t[rs].atag=0;
		t[ls].sum=c*(x-(x>>1));
		t[rs].sum=c*(x>>1);
		t[ls].mi=t[rs].mi=t[ls].mx=t[rs].mx=c;
		t[p].ctag=-1;
	}
	if(a!=0){
		t[ls].atag+=a;t[rs].atag+=a;
		t[ls].sum+=a*(x-(x>>1));
		t[rs].sum+=a*(x>>1);
		t[ls].mi+=a;t[rs].mi+=a;
		t[ls].mx+=a;t[rs].mx+=a;
		t[p].atag=0;
	}
}
void add(int p,int x,int y,int v){
	pushdown(p);
	int l=t[p].l,r=t[p].r;
	if(l==x&&r==y){
		if(l!=r) t[p].atag=v;
		t[p].mi+=v;t[p].mx+=v;
		t[p].sum+=(r-l+1)*v;
		return;
	}
	int mid=(l+r)>>1;
	if(mid>=y)add(ls,x,y,v);
	else if(mid<x)add(rs,x,y,v);
	else{
		add(ls,x,mid,v);add(rs,mid+1,y,v);
	}
	pushup(p);
}
void change(int p,int x,int y,int v){
	pushdown(p);
	int l=t[p].l,r=t[p].r;
	if(l==x&&r==y){
		if(l!=r) t[p].ctag=v;
		t[p].mi=t[p].mx=v;
		t[p].sum=(r-l+1)*v;
		return;
	}
	int mid=(l+r)>>1;
	if(mid>=y)change(ls,x,y,v);
	else if(mid<x)change(rs,x,y,v);
	else{
		change(ls,x,mid,v);change(rs,mid+1,y,v);
	}
	pushup(p);
}
int query(int p,int x,int y,int f){
	pushdown(p);
	int l=t[p].l,r=t[p].r;
	if(l==x&&r==y){
		if(f==1)return t[p].sum;
		else if(f==2)return t[p].mi;
		else return t[p].mx;
	}
	int mid=(l+r)>>1;
	if(mid>=y)return query(ls,x,y,f);
	else if(mid<x)return query(rs,x,y,f);
	else{
		if(f==1) return (query(ls,x,mid,f)+query(rs,mid+1,y,f));
		else if(f==2) return min(query(ls,x,mid,f),query(rs,mid+1,y,f));
		else return max(query(ls,x,mid,f),query(rs,mid+1,y,f));
	}
}
int main(){
	scanf("%d%d",&n,&m);
	build(1,n,1);
	while(m--){
		int c,d,x,y,v;
		scanf("%d",&c);
		if(c==1){
			scanf("%d%d%d",&d,&x,&y);
			printf("%d\n",query(1,x,y,d));
		}
		else{
			scanf("%d%d%d%d",&d,&x,&y,&v);
			if(d==1)add(1,x,y,v);
			else change(1,x,y,v);
		}
		
	}
	return 0;
}

posted @ 2020-08-13 23:58  ke_xin  阅读(58)  评论(0编辑  收藏  举报