线段树 1

题目描述
如题,已知一个数列,你需要进行下面两种操作:
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的结果。
输入输出样例
输入样例#15 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
输出样例#111
8
20
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强^_^,保证在int64/long long数据范围内)
题面
 1 #include<iostream>
 2 #include<cstdio>
 3 #define ll long long
 4 using namespace std;
 5 const ll N=100002;
 6 ll n,a[N],m,add[N*10],sum[N*10];
 7 void build(ll o,ll l,ll r)
 8 {
 9     if(l==r)
10     {
11         sum[o]=a[l];
12         return;
13     }
14     ll mid=(l+r)>>1;
15     build(o<<1,l,mid);
16     build(o<<1|1,mid+1,r);
17     sum[o]=sum[o<<1]+sum[o<<1|1];
18 }
19 ll op,x,y,k;
20 void down(ll o,ll l,ll r,ll mid)
21 {
22     if(add[o])
23     {
24         add[o<<1]+=add[o];
25         sum[o<<1]+=add[o]*(mid-l+1);
26         
27         add[o<<1|1]+=add[o];
28         sum[o<<1|1]+=add[o]*(r-(mid+1)+1);
29         
30         add[o]=0;
31     }
32 }
33 void up(ll o,ll l,ll r,ll x,ll y,ll k)
34 {
35     if(x<=l && y>=r)
36     {
37         add[o]+=k;
38         sum[o]+=k*(r-l+1);
39         return;
40     }
41     ll mid=(l+r)>>1;
42     down(o,l,r,mid);
43     if(x<=mid)up(o<<1,l,mid,x,y,k);
44     if(y>=mid+1)up(o<<1|1,mid+1,r,x,y,k);
45     sum[o]=sum[o<<1]+sum[o<<1|1];
46 }
47 ll query(ll o,ll l,ll r,ll x,ll y)
48 {
49     if(x<=l && y>=r)
50     {
51         down(o,l,r,(l+r)>>1);
52         return sum[o];
53     }
54     ll mid=(l+r)>>1;
55     down(o,l,r,mid);
56     ll tot=0;
57     if(x<=mid)tot+=query(o<<1,l,mid,x,y);
58     if(y>mid)tot+=query(o<<1|1,mid+1,r,x,y);
59     return tot; 
60 }
61 int main()
62 {
63     scanf("%lld%lld",&n,&m);
64     for(ll i=1;i<=n;i++) scanf("%d",&a[i]);
65     build(1,1,n);
66     while(m--)
67     {
68         scanf("%lld%lld%lld",&op,&x,&y);
69         if(op==1)
70         {
71             scanf("%lld",&k);
72             up(1,1,n,x,y,k);
73         }else{
74             printf("%lld\n",query(1,1,n,x,y));
75         }
76     }
77     return 0;
78 }

 

posted @ 2018-03-31 19:43  月亮茶  阅读(198)  评论(0编辑  收藏  举报