线段树

Posted fuyun_boy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树相关的知识,希望对你有一定的参考价值。

直接上题吧,半写半抄的题解

新大陆signed;

洛谷3372

https://www.luogu.org/problem/show?pid=3372

如题,已知一个数列,你需要进行下面两种操作:

1.将某区间每一个数加上x

2.求出某区间每一个数的和

输入格式:

第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3或4个整数,表示一个操作,具体如下:

操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k

操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和

输出格式:

输出包含若干行整数,即为所有操作2的结果。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 using namespace std;
  5 //==========================================
  6 struct NODE{
  7     int left,right,sum;
  8     int lazey;
  9     }tree[300005];
 10 //==========================================
 11 int a[100005],f[100005];
 12 int N,M;
 13 //==========================================
 14 void init();
 15 void build(int ,int ,int );
 16 void work();
 17 void updata(int ,int ,int ,int);
 18 int query(int ,int,int );
 19 void pushdown(int rt);
 20 //==========================================
 21 void pushdown(int rt)
 22 {
 23     int mid=( tree[rt].left + tree[rt].right )>>1;
 24     tree[rt<<1].sum+=( mid - tree[rt].left + 1 )*tree[rt].lazey;
 25     tree[(rt<<1)+1].sum+=( tree[rt].right - mid )*tree[rt].lazey;
 26     tree[rt<<1].lazey+=tree[rt].lazey;
 27     tree[(rt<<1)+1].lazey+=tree[rt].lazey;
 28     tree[rt].lazey=0;
 29 }
 30 //==========================================
 31 void updata(int rt,int left,int right,int k)
 32 {
 33     if( left<=tree[rt].left && tree[rt].right<=right ){    //全包含 
 34         tree[rt].sum+=( tree[rt].right-tree[rt].left+1 )*k;
 35         tree[rt].lazey+=k;
 36         return;
 37     }
 38     if( right<tree[rt].left || tree[rt].right <left ){    //全不包含 
 39         return;
 40     }
 41     if( tree[rt].lazey )pushdown(rt);
 42     updata( rt<<1 , left ,right , k );
 43     updata( (rt<<1)+1 , left , right ,k  );
 44     tree[rt].sum=tree[rt<<1].sum+tree[(rt<<1)+1].sum;
 45 }
 46 //==========================================
 47 int query(int rt,int left,int right)
 48 {
 49     if( left<=tree[rt].left && tree[rt].right<=right ){
 50         return tree[rt].sum;
 51     }
 52     if(right<tree[rt].left || tree[rt].right <left){
 53         return 0;
 54     }
 55     if( tree[rt].lazey )pushdown(rt);
 56     return query( rt<<1 , left , right )+query( (rt<<1)+1 , left ,right );
 57 }
 58 //==========================================
 59 void build(int rt,int left,int right)
 60 {
 61     tree[rt].left=left;
 62     tree[rt].right=right;
 63     tree[rt].lazey=0;
 64     if( left == right ){
 65         tree[rt].sum=a[left];
 66         return;
 67     }
 68     build( rt<<1 , left , (left+right)>>1 );
 69     build( (rt<<1)+1 , ((left+right)>>1)+1 , right );
 70     tree[rt].sum=tree[rt<<1].sum+tree[(rt<<1)+1].sum;
 71 }
 72 //==========================================
 73 void work()
 74 {
 75     int xx,yy,zz,kk;
 76     for(int i=1;i<=M;i++){
 77         scanf("%d%d%d*c",&xx,&yy,&zz);
 78         if(xx==1){
 79             scanf("%d*c",&kk);
 80             updata(1, yy , zz , kk );
 81         }
 82         else{
 83             printf("%d\n",query( 1 , yy , zz ));
 84         }
 85     }
 86 }
 87 //==========================================
 88 void init()
 89 {
 90     scanf("%d%d*c",&N,&M);
 91     for(int i=1;i<=N;i++){
 92         scanf("%d*c",&a[i]);
 93     }
 94 }
 95 //==========================================
 96 int main()
 97 {
 98     init();
 99     build(1,1,N);
100     work();
101     return 0;
102 }

 

以上是关于线段树的主要内容,如果未能解决你的问题,请参考以下文章

线段树

CCF(除法):线段树区间修改(50分)+线段树点修改(100分)+线段树(100分)

线段树合并

数据结构——线段树

论线段树:二

线段树