线段树的作用范围:区间单点更新和覆盖,区间多点更新和覆盖。
时间复杂度:O(logN)
原理图:
对于一个长度为N的数组,我们将一个区间(LR的区间)划分成两个单元区间。每个区域分为左区域和右区域,左区域的范围为L(L+R)/2,右区域的范围为(L+R)/2+1~R。当左区域等于右区域的时候,就说明走到最底层了。对于每个区域的下标我们规定,左区域的下标=2父节点的下标,右区域的下标=2父节点的下标+1。
结构体
struct node
{
int tl, tr;
int lazy, val;
} tree[4*maxn];
建树
void Push(int id)
{
tree[id].val=tree[id*2].val+tree[id*2+1].val;
}
void Build(int id, int tl, int tr)
{
tree[id].tl=tl;
tree[id].tr=tr;
tree[id].val=0;
tree[id].lazy=0;
if(tl== tr) tree[id].val=a[tl];
else
{
int tm=(tl+tr)/2;
Build(id*2, tl, tm);
Build(id*2+1, tm+1, tr);
Push(id);
}
}
更新
void Pushdown(int id)
{
if(tree[id].lazy==0) return ;
tree[id*2].lazy=tree[id*2+1].lazy=tree[id].lazy;
tree[id*2].val=(tree[id*2].tr-tree[id*2].tl+1)*tree[id].lazy;
tree[id*2+1].val=(tree[id*2+1].tr-tree[id*2+1].tl+1)*tree[id].lazy;
tree[id].lazy=0;
}
void Update(int id, int ql, int qr, int val)
{
int tl=tree[id].tl;
int tr=tree[id].tr;
if(ql>tr || qr<tl) return ;
if(ql<=tl && tr<=qr)
{
tree[id].lazy=val;
tree[id].val=(tree[id].tr-tree[id].tl+1)*tree[id].lazy;
return ;
}
Pushdown(id);
Update(id*2, ql, qr, val);
Update(id*2+1, ql, qr, val);
Push(id);
}
查询
int Query(int id, int ql, int qr)
{
int tl=tree[id].tl;
int tr=tree[id].tr;
int ans=0;
if(ql>tr || qr<tl) return 0;
if(ql<=tl && tr<=qr) return tree[id].val;
Pushdown(id);
ans+=Query(id*2, ql, qr);
ans+=Query(id*2+1, ql, qr);
Push(id);
return ans;
}
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1000005;
const int inf = 0x7fffffff;
int a[maxn];
struct node
{
int tl, tr, val;
} tree[4*maxn];
void Push(int id)
{
tree[id].val=min(tree[id*2].val, tree[id*2+1].val);
}
void Build(int id, int tl, int tr)
{
tree[id].tl=tl;
tree[id].tr=tr;
if(tl==tr) tree[id].val=a[tl];
else
{
int mid=(tl+tr)/2;
Build(id*2, tl, mid);
Build(id*2+1, mid+1, tr);
Push(id);
}
}
void Update(int id, int i, int val)
{
int tl=tree[id].tl;
int tr=tree[id].tr;
if(i==tl && i==tr) tree[id].val=val;
else
{
int tm=(tl+tr)/2;
if(tm>=i) Update(id*2, i, val);
else Update(id*2+1, i, val);
Push(id);
}
}
int Query(int id, int ql, int qr)
{
int tl=tree[id].tl;
int tr=tree[id].tr;
if(ql<=tl && tr<=qr) return tree[id].val;
int tm=(tl+tr)/2;
int res1=inf, res2=inf;
if(tm>=ql) res1=Query(id*2, ql, qr);
if(tm<qr) res2=Query(id*2+1, ql, qr);
return min(res1, res2);
}
int main()
{
int i, n, q, op, l, r, val;
scanf("%d", &n);
for(i=1; i<=n; i++)
{
scanf("%d", &a[i]);
}
scanf("%d", &q);
Build(1, 1, n);
while(q--)
{
scanf("%d", &op);
if(op==0)
{
scanf("%d%d", &l, &r);
printf("%d\n", Query(1, l, r));
}
else
{
scanf("%d%d", &i, &val);
Update(1, i, val);
}
}
return 0;
}
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1000005;
const int inf = 0x7fffffff;
int a[maxn];
struct node
{
int tl, tr, val, lazy;
} tree[4*maxn];
void push(int id)
{
tree[id].val=tree[id*2].val+tree[id*2+1].val;
}
void pushdown(int id)
{
if(tree[id].lazy==0) return ;
tree[id*2].lazy=tree[id*2+1].lazy=tree[id].lazy;
tree[id*2].val=(tree[id*2].tr-tree[id*2].tl+1)*tree[id].lazy;
tree[id*2+1].val=(tree[id*2+1].tr-tree[id*2+1].tl+1)*tree[id].lazy;
tree[id].lazy=0;
}
void build(int id, int tl, int tr)
{
tree[id].tl=tl;
tree[id].tr=tr;
tree[id].val=0;
tree[id].lazy=0;
if(tl==tr) tree[id].val=a[tl];
else
{
int tm=(tl+tr)/2;
build(id*2, tl, tm);
build(id*2+1, tm+1, tr);
push(id);
}
}
void update(int id, int ql, int qr, int val)
{
int tl=tree[id].tl;
int tr=tree[id].tr;
if(ql>tr || qr<tl) return ;
if(ql<=tl && tr<=qr)
{
tree[id].lazy=val;
tree[id].val=(tree[id].tr-tree[id].tl+1)*tree[id].lazy;
return ;
}
pushdown(id);
update(id*2, ql, qr, val);
update(id*2+1, ql, qr, val);
push(id);
}
int query(int id, int ql, int qr)
{
int tl=tree[id].tl;
int tr=tree[id].tr;
int ans=0;
if(ql>tr || qr<tl) return 0;
if(ql<=tl && tr<=qr) return tree[id].val;
pushdown(id);
ans+=query(id*2, ql, qr);
ans+=query(id*2+1, ql, qr);
push(id);
return ans;
}
int main()
{
int n, i, q, l, r, val, op;
scanf("%d", &n);
for(i=1; i<=n; i++)
{
scanf("%d", &a[i]);
}
build(1, 1, n);
scanf("%d", &q);
while(q--)
{
scanf("%d", &op);
if(op==0)
{
scanf("%d%d", &l, &r);
printf("%d\n", query(1, l, r));
}
else
{
scanf("%d%d%d", &l, &r, &val);
update(1, l, r, val);
}
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1000005;
const int inf = 0x7fffffff;
int vis[maxn];
int ans=0;
int a[maxn];
struct re
{
int l, r;
} q[maxn];
struct node
{
int tl, tr, val, lazy;
} tree[4*maxn];
void Build(int id, int tl, int tr)
{
tree[id].tl=tl;
tree[id].tr=tr;
tree[id].val=0;
tree[id].lazy=0;
if(tl+1==tr) return ;
else
{
int tm=(tl+tr)/2;
Build(id*2, tl, tm);
Build(id*2+1, tm, tr);
}
}
void Pushdown(int id)
{
if(tree[id].lazy==0) return ;
tree[id*2].lazy=tree[id*2+1].lazy=tree[id].lazy;
tree[id*2].val=tree[id*2+1].val=tree[id].lazy;
tree[id].lazy=0;
}
void Update(int id, int ql, int qr, int val)
{
int tl=tree[id].tl;
int tr=tree[id].tr;
if(ql<=tl && tr<=qr)
{
tree[id].lazy=val;
tree[id].val=val;
return ;
}
Pushdown(id);
int tm=(tl+tr)/2;
if(tm>ql) Update(id*2, ql, qr, val);
if(tm<qr) Update(id*2+1, ql, qr, val);
}
void Query(int id, int ql, int qr)
{
int tl=tree[id].tl;
int tr=tree[id].tr;
if(tl+1==tr)
{
if(vis[tree[id].val]==0)
{
vis[tree[id].val]=1;
ans++;
}
return ;
}
Pushdown(id);
int tm=(tl+tr)/2;
if(tm>ql) Query(id*2, ql, qr);
if(tm<qr) Query(id*2+1, ql, qr);
}
void init()
{
memset(vis,0,sizeof(vis));
memset(a,0,sizeof(a));
ans=0;
}
int main()
{
init();
int i, n, l, k=0;
scanf("%d%d", &n, &l);
for(i=1; i<=n; i++)
{
scanf("%d%d", &q[i].l, &q[i].r);
a[k++]=q[i].l;
a[k++]=q[i].r;
}
sort(a, a+k);
int len=unique(a, a+k)-a;
Build(1, 1, len);
for(i=1; i<=n; i++)
{
int l=lower_bound(a,a+len,q[i].l)-a+1;
int r=lower_bound(a,a+len,q[i].r)-a+1;
Update(1, l, r, i);
}
vis[0]=1;
Query(1, 1, len);
printf("%d\n", ans);
return 0;
}
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1e5+5;
const int inf = 0x7fffffff;
struct node
{
int tl, tr;
int lazyset, lazyadd, val;
} tree[4*maxn];
int a[maxn];
void push(int id)
{
tree[id].val=tree[2*id].val+tree[2*id+1].val;
}
void build(int id, int tl, int tr)
{
tree[id].tl=tl;
tree[id].tr=tr;
if(tl==tr) tree[id].val=a[tl];
else
{
int tm=(tr+tl)/2;
build(id*2,tl,tm);
build(id*2+1,tm+1,tr);
push(id);
}
}
void pushdown(int id)
{
if(tree[id].lazyset!=0)
{
tree[id*2].lazyset=tree[id].lazyset;
tree[id*2+1].lazyset=tree[id].lazyset;
tree[id*2].lazyadd=tree[id].lazyadd;
tree[id*2+1].lazyadd=tree[id].lazyadd;
int ans=tree[id].lazyset+tree[id].lazyadd;
tree[id*2].val=(tree[id*2].tr-tree[id*2].tl+1)*ans;
tree[id*2+1].val=(tree[id*2+1].tr-tree[id*2+1].tl+1)*ans;
tree[id].lazyset=0;
tree[id].lazyadd=0;
}
else if(tree[id].lazyadd!=0)
{
tree[id*2].lazyadd+=tree[id].lazyadd;
tree[id*2+1].lazyadd+=tree[id].lazyadd;
tree[id*2].val+=(tree[id*2].tr-tree[id*2].tl+1)*tree[id].lazyadd;
tree[id*2+1].val+=(tree[id*2+1].tr-tree[id*2+1].tl+1)*tree[id].lazyadd;
tree[id].lazyadd=0;
}
}
void putset(int id, int val)
{
tree[id].lazyadd=0;
tree[id].lazyset=val;
tree[id].val=(tree[id].tr-tree[id].tl+1)*val;
}
void Set(int id, int ql, int qr, int val)
{
int tl=tree[id].tl;
int tr=tree[id].tr;
if(ql>tr || qr<tl) return ;
if(ql<=tl && tr<=qr)
{
putset(id, val);
return ;
}
pushdown(id);
Set(id*2, ql, qr, val);
Set(id*2+1, ql, qr, val);
push(id);
}
void putadd(int id, int val)
{
tree[id].lazyadd+=val;
tree[id].val+=(tree[id].tr-tree[id].tl+1)*val;
}
void add(int id, int ql, int qr, int val)
{
int tl=tree[id].tl;
int tr=tree[id].tr;
if(ql>tr || qr<tl) return ;
if(ql<=tl && tr<=qr)
{
putadd(id, val);
return ;
}
pushdown(id);
add(id*2, ql, qr, val);
add(id*2+1, ql, qr, val);
push(id);
}
int getval(int id, int ql, int qr)
{
int tl=tree[id].tl;
int tr=tree[id].tr;
int ans=0;
if(ql>tr || qr<tl) return 0;
if(ql<=tl && tr<=qr) return tree[id].val;
pushdown(id);
ans+=getval(id*2, ql, qr);
ans+=getval(id*2+1, ql, qr);
push(id);
return ans;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=1; i<=n+1; i++)
scanf("%d",&a[i]);
build(1,1,n+1);
while(q--)
{
int op,l,r,val;
scanf("%d%d%d%d",&op,&l,&r,&val);
if(!op)add(1,l+1,r+1,val);
else Set(1,l+1,r+1,val);
printf("%d\n",getval(1,1,n+1));
}
return 0;
}