洛谷P3372 【模板】線段樹 1

題目描述

如題,已知一個數列,你須要進行下面兩種操做:ios

1.將某區間每個數加上xide

2.求出某區間每個數的和spa

輸入輸出格式

輸入格式:code

第一行包含兩個整數N、M,分別表示該數列數字的個數和操做的總個數。blog

第二行包含N個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。get

接下來M行每行包含3或4個整數,表示一個操做,具體以下:io

操做1: 格式:1 x y k 含義:將區間[x,y]內每一個數加上kevent

操做2: 格式:2 x y 含義:輸出區間[x,y]內每一個數的和class

輸出格式:stream

輸出包含若干行整數,即爲全部操做2的結果。

輸入輸出樣例

輸入樣例#1: 
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
輸出樣例#1: 
11
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 ll read()
 6 {
 7     ll x=0,f=1;
 8     char ch=getchar();
 9     while(ch<'0'||ch>'9')
10     {
11         if(ch=='-')
12             f=-1;
13         ch=getchar();
14     }
15     while(ch>='0'&&ch<='9')
16     {
17         x=x*10+ch-'0';
18         ch=getchar();
19     }
20     return x*f;
21 }
22 ll n,m,a,b,t,x,y,z;
23 ll tree[100005],tree1[100005];
24 void add(ll*z,ll x,ll num)
25 {
26     while(x<=n)
27     {
28         z[x]+=num;
29         x+=x&(-x);
30     }
31 }
32 ll getsum(ll*z,ll x)
33 {
34     ll sum=0;
35     while(x>0)
36     {
37         sum+=z[x];
38         x-=x&(-x);
39     }
40     return sum;
41 }
42 int main()
43 {
44     n=read(),m=read();
45     for(ll i=1; i<=n; i++)
46     {
47         a=read();
48         b=a-b;
49         add(tree,i,b);
50         add(tree1,i,(i-1)*b);
51         b=a;
52     }
53     for(ll i=1; i<=m; i++)
54     {
55         t=read();
56         if (t==1)
57         {
58             x=read(),y=read(),z=read();
59             add(tree,x,z);
60             add(tree,y+1,-z);
61             add(tree1,x,z*(x-1));
62             add(tree1,y+1,-z*y);
63         }
64         else
65         {
66             x=read(),y=read();
67             printf("%lld\n",(y*getsum(tree,y)-(x-1)*getsum(tree,x-1))-(getsum(tree1,y)-getsum(tree1,x-1)));
68         }
69     }
70     return 0;
71 }
View Code
相關文章
相關標籤/搜索