线段树

线段树的作用:

1.多次查询区间的最大值,最小值,以及区间和

2.多次更新区间的元素值(可以元素值替换,也可加上一个给定输入值)

#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <queue>
#define MAXN 100010
#define inf 0x3f3f3f3f
#include<iostream>
using namespace std;
struct node{
    int l,r;//区间[l,r]
    int add;//区间的延时标记
    int sum;//区间和
    int mx; //区间最大值
    int mn; //区间最小值
}tree[MAXN<<2];//一定要开到4倍多的空间

void pushup(int index){
    tree[index].sum = tree[index<<1].sum+tree[index<<1|1].sum;
    tree[index].mx = max(tree[index<<1].mx,tree[index<<1|1].mx);
    tree[index].mn = min(tree[index<<1].mn,tree[index<<1|1].mn);
}
void pushdown(int index){
    //说明该区间之前更新过
    //要想更新该区间下面的子区间,就要把上次更新该区间的值向下更新
    if(tree[index].add){
        //替换原来的值
        /*
        tree[index<<1].sum = (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
        tree[index<<1|1].sum = (tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
        tree[index<<1].mx = tree[index].add;
        tree[index<<1|1].mx = tree[index].add;
        tree[index<<1].mn = tree[index].add;
        tree[index<<1|1].mn = tree[index].add;
        tree[index<<1].add = tree[index].add;
        tree[index<<1|1].add = tree[index].add;
        tree[index].add = 0;*/
        //在原来的值的基础上加上val
        tree[index<<1].sum += (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
        tree[index<<1|1].sum +=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
        tree[index<<1].mx += tree[index].add;
        tree[index<<1|1].mx += tree[index].add;
        tree[index<<1].mn += tree[index].add;
        tree[index<<1|1].mn += tree[index].add;
        tree[index<<1].add += tree[index].add;
        tree[index<<1|1].add += tree[index].add;
        tree[index].add = 0;

    }
}
void build(int l,int r,int index){
    tree[index].l = l;
    tree[index].r = r;
    tree[index].add = 0;//刚开始一定要清0
    if(l == r){
        scanf("%d",&tree[index].sum);
        tree[index].mn = tree[index].mx = tree[index].sum;
        return ;
    }
    int mid = (l+r)>>1;
    build(l,mid,index<<1);
    build(mid+1,r,index<<1|1);
    pushup(index);
}
void updata(int l,int r,int index,int val){
    if(l <= tree[index].l && r >= tree[index].r){
        /*把原来的值替换成val,因为该区间有tree[index].r-tree[index].l+1
        个数,所以区间和 以及 最值为:
        */
        /*
tree[index].sum = (tree[index].r-tree[index].l+1)*val; tree[index].mn = val; tree[index].mx = val; tree[index].add = val;//延时标记
*/ //在原来的值的基础上加上val,因为该区间有tree[index].r-tree[index].l+1 //个数,所以区间和 以及 最值为: tree[index].sum += (tree[index].r-tree[index].l+1)*val; tree[index].mn += val; tree[index].mx += val; tree[index].add += val;//延时标记 return ; } pushdown(index); int mid = (tree[index].l+tree[index].r)>>1; if(l <= mid){ updata(l,r,index<<1,val); } if(r > mid){ updata(l,r,index<<1|1,val); } pushup(index); } int query(int l,int r,int index){ if(l <= tree[index].l && r >= tree[index].r){ //return tree[index].sum; return tree[index].mx; //return tree[index].mn; } pushdown(index); int mid = (tree[index].l+tree[index].r)>>1; int ans = 0; int Max = 0; int Min = inf; if(l <= mid){ ans += query(l,r,index<<1); Max = max(query(l,r,index<<1),Max); Min = min(query(l,r,index<<1),Min); } if(r > mid){ ans += query(l,r,index<<1|1); Max = max(query(l,r,index<<1|1),Max); Min = min(query(l,r,index<<1|1),Min); } //return ans; return Max; //return Min; } int query1(int l,int r,int index){ if(l <= tree[index].l && r >= tree[index].r){ //return tree[index].sum; // return tree[index].mx; return tree[index].mn; } pushdown(index); int mid = (tree[index].l+tree[index].r)>>1; int Min = inf; if(l <= mid){ Min = min(query(l,r,index<<1),Min); } if(r > mid){ Min = min(query(l,r,index<<1|1),Min); } return Min; } int query2(int l,int r,int index){ if(l <= tree[index].l && r >= tree[index].r){ return tree[index].sum; } pushdown(index); int mid = (tree[index].l+tree[index].r)>>1; int ans = 0; if(l <= mid){ ans += query(l,r,index<<1); } if(r > mid){ ans += query(l,r,index<<1|1); } return ans; } int main() { int n,m,q,x,y,z; while(~scanf("%d%d",&n,&m)){ build(1,n,1); while(m--){ scanf("%d",&q); if(q == 1){ cout<<"查询:(x,y)的最大值"<<endl; scanf("%d %d",&x,&y); cout<<query(x,y,1)<<endl; } else if(q==2){ cout<<"查询:(x,y)的最小值"<<endl; scanf("%d %d",&x,&y); cout<<query1(x,y,1)<<endl; } else if(q==3){ cout<<"查询:(x,y)的和"<<endl; scanf("%d %d",&x,&y); cout<<query2(x,y,1)<<endl; } else{ cout<<"更新(x,y),区间每个数加上z:"<<endl; scanf("%d %d %d",&x,&y,&z); updata(x,y,1,z); for(int i = 1; i <= n; ++i){ printf("a[%d] = %d\n",i,query(i,i,1)); } } } } return 0; } /* 8 10 8 1 9 10 2 4 5 0 */

2.主席树  

作用:

 

 

 

 

 

 

 

 

相关博客:

http://www.imooc.com/article/73393

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 long long n,m,ans,x,y,ch,val;
 5 struct ahah
 6 {
 7     long long l,r,sum,f;
 8 } tree[200000<<2];
 9 void build(int k,int l,int r)
10 {
11     tree[k].l=l;
12     tree[k].r=r;
13     if(tree[k].l==tree[k].r)
14     {
15         scanf("%lld",&tree[k].sum);//输入端点的值
16         //tree[k].sum=0;
17         // cout<<"?"<<endl;
18         return ;
19     }
20     long long mid=(tree[k].l+tree[k].r)>>1;
21     build(k<<1,l,mid);
22     build(k<<1|1,mid+1,r);
23     tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
24 }
25 void update(int k)
26 {
27     if(tree[k].l==tree[k].r)
28     {
29         tree[k].sum+=y;
30         return ;
31     }
32     long long mid=(tree[k].l+tree[k].r)>>1;
33     if(x<=mid)
34         update(k<<1);
35     else
36         update(k<<1|1);
37     tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
38 }
39 void down(long long k)
40 {
41     tree[k<<1].f+=tree[k].f;
42     tree[k<<1|1].f+=tree[k].f;
43     tree[k<<1].sum+=(tree[k<<1].r-tree[k<<1].l+1)*tree[k].f;
44     tree[k<<1|1].sum+=(tree[k<<1|1].r-tree[k<<1|1].l+1)*tree[k].f;
45     tree[k].f=0;
46 }
47 void query(int k)
48 {
49     if(x<=tree[k].l&&y>=tree[k].r)
50     {
51         ans+=tree[k].sum;
52         return ;
53     }
54     if(tree[k].f)
55         down(k);
56     long long mid=(tree[k].l+tree[k].r)>>1;
57     if(x<=mid)
58         query(k<<1);
59     if(y>mid)
60         query(k<<1|1);
61 }
62 void add(long long k)
63 {
64     if(tree[k].l>=x&&tree[k].r<=y)
65     {
66         tree[k].sum+=(tree[k].r-tree[k].l+1)*val;
67         tree[k].f+=val;
68         return ;
69     }
70     if(tree[k].f)
71         down(k);
72     long long mid=(tree[k].l+tree[k].r)>>1;
73     if(x<=mid)
74         add(k<<1);
75     if(y>mid)
76         add(k<<1|1);
77     tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
78 }
79 int main()
80 {
81     scanf("%lld%lld",&n,&m);//n个数,m个操作
82     build(1,1,n);//输入n个端点的值
83     for(int i=1; i<=m; i++)
84     {
85         ans=0;
86         cin>>ch>>x>>y;//操作类型,区间左下标,区间右下标
87         if(ch==1)//区间修改
88         {
89             cin>>val;
90             add(1);
91         }
92         else//区间查询
93         {
94             query(1);
95             cout<<ans<<"\n";
96         }
97     }
98 }
View Code

输入:

8  4

4 2 5 7 9 1 0 3

2 1 3

1 1 3

2 1 3

2 1 1

输出:

11

20

7

https://blog.csdn.net/qq_36553623/article/details/82988354

  1 #include <string.h>
  2 #include <algorithm>
  3 #include <stdio.h>
  4 #include <math.h>
  5 #include <queue>
  6 #define MAXN 100010
  7 #define inf 0x3f3f3f3f
  8 #include<iostream>
  9 using namespace std;
 10 
 11 struct node{
 12     int l,r;//区间[l,r]
 13     int add;//区间的延时标记
 14     int sum;//区间和
 15     int mx; //区间最大值
 16     int mn; //区间最小值
 17 }tree[MAXN<<2];//一定要开到4倍多的空间
 18 
 19 void pushup(int index){
 20     tree[index].sum = tree[index<<1].sum+tree[index<<1|1].sum;
 21     tree[index].mx = max(tree[index<<1].mx,tree[index<<1|1].mx);
 22     tree[index].mn = min(tree[index<<1].mn,tree[index<<1|1].mn);
 23 }
 24 void pushdown(int index){
 25     //说明该区间之前更新过
 26     //要想更新该区间下面的子区间,就要把上次更新该区间的值向下更新
 27     if(tree[index].add){
 28         //替换原来的值
 29         /*
 30         tree[index<<1].sum = (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
 31         tree[index<<1|1].sum = (tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
 32         tree[index<<1].mx = tree[index].add;
 33         tree[index<<1|1].mx = tree[index].add;
 34         tree[index<<1].mn = tree[index].add;
 35         tree[index<<1|1].mn = tree[index].add;
 36         tree[index<<1].add = tree[index].add;
 37         tree[index<<1|1].add = tree[index].add;
 38         tree[index].add = 0;*/
 39         //在原来的值的基础上加上val
 40 
 41         tree[index<<1].sum += (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
 42         tree[index<<1|1].sum +=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
 43         tree[index<<1].mx += tree[index].add;
 44         tree[index<<1|1].mx += tree[index].add;
 45         tree[index<<1].mn += tree[index].add;
 46         tree[index<<1|1].mn += tree[index].add;
 47         tree[index<<1].add += tree[index].add;
 48         tree[index<<1|1].add += tree[index].add;
 49         tree[index].add = 0;
 50 
 51     }
 52 }
 53 void build(int l,int r,int index){
 54     tree[index].l = l;
 55     tree[index].r = r;
 56     tree[index].add = 0;//刚开始一定要清0
 57     if(l == r){
 58         scanf("%d",&tree[index].sum);
 59         tree[index].mn = tree[index].mx = tree[index].sum;
 60         return ;
 61     }
 62     int mid = (l+r)>>1;
 63     build(l,mid,index<<1);
 64     build(mid+1,r,index<<1|1);
 65     pushup(index);
 66 }
 67 void updata(int l,int r,int index,int val){
 68     if(l <= tree[index].l && r >= tree[index].r){
 69         /*把原来的值替换成val,因为该区间有tree[index].r-tree[index].l+1
 70         个数,所以区间和 以及 最值为:
 71         */
 72         /*tree[index].sum = (tree[index].r-tree[index].l+1)*val;
 73         tree[index].mn = val;
 74         tree[index].mx = val;
 75         tree[index].add = val;//延时标记*/
 76         //在原来的值的基础上加上val,因为该区间有tree[index].r-tree[index].l+1
 77         //个数,所以区间和 以及 最值为:
 78         tree[index].sum += (tree[index].r-tree[index].l+1)*val;
 79         tree[index].mn += val;
 80         tree[index].mx += val;
 81         tree[index].add += val;//延时标记
 82 
 83         return ;
 84     }
 85     pushdown(index);
 86     int mid = (tree[index].l+tree[index].r)>>1;
 87     if(l <= mid){
 88         updata(l,r,index<<1,val);
 89     }
 90     if(r > mid){
 91         updata(l,r,index<<1|1,val);
 92     }
 93     pushup(index);
 94 }
 95 int query(int l,int r,int index){
 96     if(l <= tree[index].l && r >= tree[index].r){
 97         //return tree[index].sum;
 98         return tree[index].mx;
 99         //return tree[index].mn;
100     }
101     pushdown(index);
102     int mid = (tree[index].l+tree[index].r)>>1;
103     int ans = 0;
104     int Max = 0;
105     int Min = inf;
106     if(l <= mid){
107         ans += query(l,r,index<<1);
108         Max = max(query(l,r,index<<1),Max);
109         Min = min(query(l,r,index<<1),Min);
110     }
111     if(r > mid){
112         ans += query(l,r,index<<1|1);
113         Max = max(query(l,r,index<<1|1),Max);
114         Min = min(query(l,r,index<<1|1),Min);
115     }
116     //return ans;
117     return Max;
118     //return Min;
119 }
120 int main()
121 {
122     int n,m,q,x,y,z;
123     while(~scanf("%d%d",&n,&m)){
124         build(1,n,1);
125         while(m--){
126             scanf("%d",&q);
127             if(q == 1){
128                 cout<<"查询:(x,y)"<<endl;
129                 scanf("%d %d",&x,&y);
130                 cout<<query(x,y,1)<<endl;
131             }
132             else{
133                 cout<<"更新(x,y)为z:"<<endl;
134                 scanf("%d %d %d",&x,&y,&z);
135                 updata(x,y,1,z);
136                 for(int i = 1; i <= n; ++i){
137                     printf("a[%d] = %d\n",i,query(i,i,1));
138                 }
139             }
140         }
141     }
142     return 0;
143 }
View Code

 

#include <string.h>#include <algorithm>#include <stdio.h>#include <math.h>#include <queue>#define MAXN 100010#define inf 0x3f3f3f3f#include<iostream>using namespace std;struct node{    int l,r;//区间[l,r]    int add;//区间的延时标记    int sum;//区间和    int mx; //区间最大值    int mn; //区间最小值}tree[MAXN<<2];//一定要开到4倍多的空间
void pushup(int index){    tree[index].sum = tree[index<<1].sum+tree[index<<1|1].sum;    tree[index].mx = max(tree[index<<1].mx,tree[index<<1|1].mx);    tree[index].mn = min(tree[index<<1].mn,tree[index<<1|1].mn);}void pushdown(int index){    //说明该区间之前更新过    //要想更新该区间下面的子区间,就要把上次更新该区间的值向下更新    if(tree[index].add){        //替换原来的值        /*        tree[index<<1].sum = (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;        tree[index<<1|1].sum = (tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;        tree[index<<1].mx = tree[index].add;        tree[index<<1|1].mx = tree[index].add;        tree[index<<1].mn = tree[index].add;        tree[index<<1|1].mn = tree[index].add;        tree[index<<1].add = tree[index].add;        tree[index<<1|1].add = tree[index].add;        tree[index].add = 0;*/        //在原来的值的基础上加上val        tree[index<<1].sum += (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;        tree[index<<1|1].sum +=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;        tree[index<<1].mx += tree[index].add;        tree[index<<1|1].mx += tree[index].add;        tree[index<<1].mn += tree[index].add;        tree[index<<1|1].mn += tree[index].add;        tree[index<<1].add += tree[index].add;        tree[index<<1|1].add += tree[index].add;        tree[index].add = 0;
    }}void build(int l,int r,int index){    tree[index].l = l;    tree[index].r = r;    tree[index].add = 0;//刚开始一定要清0    if(l == r){        scanf("%d",&tree[index].sum);        tree[index].mn = tree[index].mx = tree[index].sum;        return ;    }    int mid = (l+r)>>1;    build(l,mid,index<<1);    build(mid+1,r,index<<1|1);    pushup(index);}void updata(int l,int r,int index,int val){    if(l <= tree[index].l && r >= tree[index].r){        /*把原来的值替换成val,因为该区间有tree[index].r-tree[index].l+1        个数,所以区间和 以及 最值为:        */        /*tree[index].sum = (tree[index].r-tree[index].l+1)*val;        tree[index].mn = val;        tree[index].mx = val;        tree[index].add = val;//延时标记*/        //在原来的值的基础上加上val,因为该区间有tree[index].r-tree[index].l+1        //个数,所以区间和 以及 最值为:        tree[index].sum += (tree[index].r-tree[index].l+1)*val;        tree[index].mn += val;        tree[index].mx += val;        tree[index].add += val;//延时标记        return ;    }    pushdown(index);    int mid = (tree[index].l+tree[index].r)>>1;    if(l <= mid){        updata(l,r,index<<1,val);    }    if(r > mid){        updata(l,r,index<<1|1,val);    }    pushup(index);}int query(int l,int r,int index){    if(l <= tree[index].l && r >= tree[index].r){        //return tree[index].sum;        return tree[index].mx;        //return tree[index].mn;    }    pushdown(index);    int mid = (tree[index].l+tree[index].r)>>1;    int ans = 0;    int Max = 0;    int Min = inf;    if(l <= mid){        ans += query(l,r,index<<1);        Max = max(query(l,r,index<<1),Max);        Min = min(query(l,r,index<<1),Min);    }    if(r > mid){        ans += query(l,r,index<<1|1);        Max = max(query(l,r,index<<1|1),Max);        Min = min(query(l,r,index<<1|1),Min);    }    //return ans;    return Max;    //return Min;}int query1(int l,int r,int index){    if(l <= tree[index].l && r >= tree[index].r){        //return tree[index].sum;       // return tree[index].mx;        return tree[index].mn;    }    pushdown(index);    int mid = (tree[index].l+tree[index].r)>>1;    int Min = inf;    if(l <= mid){        Min = min(query(l,r,index<<1),Min);    }    if(r > mid){        Min = min(query(l,r,index<<1|1),Min);    }    return Min;}
int query2(int l,int r,int index){    if(l <= tree[index].l && r >= tree[index].r){        return tree[index].sum;    }    pushdown(index);    int mid = (tree[index].l+tree[index].r)>>1;    int ans = 0;    if(l <= mid){        ans += query(l,r,index<<1);    }    if(r > mid){        ans += query(l,r,index<<1|1);    }    return ans;}
int main(){    int n,m,q,x,y,z;    while(~scanf("%d%d",&n,&m)){        build(1,n,1);        while(m--){            scanf("%d",&q);            if(q == 1){                cout<<"查询:(x,y)的最大值"<<endl;                scanf("%d %d",&x,&y);                cout<<query(x,y,1)<<endl;            }            else if(q==2){                 cout<<"查询:(x,y)的最小值"<<endl;                 scanf("%d %d",&x,&y);                 cout<<query1(x,y,1)<<endl;            }            else if(q==3){                 cout<<"查询:(x,y)的和"<<endl;                 scanf("%d %d",&x,&y);                 cout<<query2(x,y,1)<<endl;            }            else{                cout<<"更新(x,y),区间每个数加上z:"<<endl;                scanf("%d %d %d",&x,&y,&z);                updata(x,y,1,z);                for(int i = 1; i <= n; ++i){                    printf("a[%d] = %d\n",i,query(i,i,1));                }            }        }    }    return 0;}/*8 108 1 9 10 2 4 5 0*/

 

 

zkw线段树

https://blog.csdn.net/keshuqi/article/details/52205884

https://www.cnblogs.com/Parsnip/p/10785894.html

posted @ 2019-07-25 15:33  saaas  阅读(113)  评论(0)    收藏  举报