线段树

线段树是一种维护区间信息的数据结构,用空间换时间,查询和修改基本都是O(logn)的。

线段树很好理解,常见模型比较固定。如单点修改,区间查询,区间修改等。

 1 //单点修改,区间查询 
 2 
 3 int a[maxn],sum[4*maxn];
 4 void build(int p,int l,int r) {
 5     if(l==r) sum[p]=a[l];
 6     else {
 7         int mid=l+(r-l)/2;
 8         build(2*p,l,mid);
 9         build(2*p+1,mid+1,r);
10         sum[p]=sum[2*p]+sum[2*p+1];
11     }
12 }
13 void modify(int p,int l,int r,int x,int y) {
14     if(l==r) sum[p]+=y;
15     else {
16         int mid=l+(r-l)/2;
17         if(x<=mid) modify(2*p,l,mid,x,y);
18         else modify(2*p+1,mid+1,r,x,y);
19         sum[p]=sum[2*p]+sum[2*p+1];
20     }
21 }
22 int query(int p,int l,int r,int x,int y) {
23     if(x<=l&&y>=r) return sum[p];
24     int mid=l+(r-l)/2,ans=0;
25     if(x<=mid) ans+=query(2*p,l,mid,x,y);
26     if(y>mid) ans+=query(2*p+1,mid+1,r,x,y);
27     return ans;
28 }
 1 //区间修改,区间查询 
 2 
 3 typedef long long ll;
 4 ll a[maxn],sum[4*maxn],lazy[4*maxn];
 5 void build(int p,int l,int r) {
 6     if(l==r) sum[p]=a[l];
 7     else {
 8         int mid=l+(r-l)/2;
 9         build(2*p,l,mid);
10         build(2*p+1,mid+1,r);
11         sum[p]=sum[2*p]+sum[2*p+1];
12     }
13 }
14 void add(int p,int l,int r,ll d) {
15     lazy[p]+=d;
16     sum[p]+=d*(r-l+1);
17 }
18 void pushdown(int p,int l,int r) {
19     int mid=l+(r-l)/2;
20     add(2*p,l,mid,lazy[p]);
21     add(2*p+1,mid+1,r,lazy[p]);
22     lazy[p]=0;
23 }
24 void modify(int p,int l,int r,int x,int y,ll d) {
25     if(x<=l&&y>=r) add(p,l,r,d);
26     else {
27         pushdown(p,l,r);
28         int mid=l+(r-l)/2;
29         if(x<=mid) modify(2*p,l,mid,x,y,d);
30         if(y>mid) modify(2*p+1,mid+1,r,x,y,d);
31         sum[p]=sum[2*p]+sum[2*p+1];
32     }
33 }
34 ll query(int p,int l,int r,int x,int y) {
35     if(x<=l&&y>=r) return sum[p];
36     pushdown(p,l,r);
37     int mid=l+(r-l)/2;
38     ll ans=0;
39     if(x<=mid) ans+=query(2*p,l,mid,x,y);
40     if(y>mid) ans+=query(2*p+1,mid+1,r,x,y);
41     return ans;
42 } 
原文地址:https://www.cnblogs.com/Mr94Kevin/p/9742908.html