线段树
|
单点查询 |
区间查询 |
单点修改 |
区间修改 |
预处理 |
特点 |
数组 |
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;
}