【洛谷 p3372】模板-线段树 1(数据结构--线段树)

题目:已知一个数列,你需要进行下面两种操作:1.将某区间每一个数加上x;2.求出某区间每一个数的和。

解法:如题,模版题。需要加上 lazy 标记,也就是我的 upd。lazy 标记的思路就是对一个结点更新(算和)了,但不继续更新它下面的结点,而是标记下来(每个数需加上的值)。注意——边界判断,不能调用a[-1]之类的。而对于叶子结点的upd,为0或有值都没有关系,反正它已经没有孩子了嘛。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 using namespace std;
 6 #define N 100010
 7 typedef long long LL;
 8 
 9 int n,m,len=0;
10 struct node{int l,r,lc,rc;LL d,upd;}a[2*N];
11 
12 void build(int l,int r)
13 {
14     int x=++len;
15     a[x].l=l,a[x].r=r,a[x].d=a[x].upd=0;
16     a[x].lc=a[x].rc=-1;
17     if (l<r)
18     {
19       int mid=(l+r)>>1;
20       a[x].lc=len+1,build(l,mid);
21       a[x].rc=len+1,build(mid+1,r);
22     }
23 }
24 void updata(int x)
25 {
26     if (!a[x].upd) return;
27     LL d=a[x].upd;
28     a[x].upd=0;
29     int lc=a[x].lc,rc=a[x].rc;
30     if (lc!=-1) a[lc].d+=d*(a[lc].r-a[lc].l+1),a[lc].upd+=d;
31     if (rc!=-1) a[rc].d+=d*(a[rc].r-a[rc].l+1),a[rc].upd+=d;//-1 +=
32 }
33 void ins(int x,int l,int r,int d)
34 {
35     if (a[x].l==l && a[x].r==r) {a[x].d+=d*(a[x].r-a[x].l+1);a[x].upd+=d;return;}
36     updata(x);//
37     int lc=a[x].lc,rc=a[x].rc,mid=(a[x].l+a[x].r)>>1;
38     if (r<=mid) ins(lc,l,r,d);
39     else if (l>mid) ins(rc,l,r,d);
40     else ins(lc,l,mid,d),ins(rc,mid+1,r,d);
41     a[x].d=a[lc].d+a[rc].d;
42     //a[x].upd=a[lc].upd+a[rc].upd;
43 }
44 LL query(int x,int l,int r)
45 {
46     updata(x);
47     if (a[x].l==l && a[x].r==r) return a[x].d;
48     int lc=a[x].lc,rc=a[x].rc,mid=(a[x].l+a[x].r)>>1;
49     if (r<=mid) return query(lc,l,r);
50     else if (l>mid) return query(rc,l,r);
51     else return query(lc,l,mid)+query(rc,mid+1,r);
52 }
53 int main()
54 {
55     scanf("%d%d",&n,&m);
56     int x,y,k; LL d;
57     build(1,n);
58     for (int i=1;i<=n;i++)
59     {
60       scanf("%lld",&d);
61       ins(1,i,i,d);
62     }
63     while (m--)
64     {
65       scanf("%d",&k);
66       if (k==1)
67       {
68         scanf("%d%d%lld",&x,&y,&d);
69         ins(1,x,y,d);
70       }
71       else
72       {
73         scanf("%d%d",&x,&y);
74         printf("%lld
",query(1,x,y));
75         //for (int i=1;i<=len;i++)
76         //  printf("%d %d %d %lld %lld
",i,a[i].l,a[i].r,a[i].d,a[i].upd);
77       }
78     }
79     return 0;
80 }
原文地址:https://www.cnblogs.com/konjak/p/6072579.html