1. 程式人生 > >P3372 【模板】線段樹 1

P3372 【模板】線段樹 1

load color 求和 整數 數字 amp article http cst

題目描述

如題,已知一個數列,你需要進行下面兩種操作:

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:
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數據範圍內)

樣例說明:

技術分享

在這裏提醒大家一點

如果你用的是Dev-c++的5.92版本的話,用%lld輸入可能會發生運行時錯誤

這時候如果你確保你的程序百分百對的話,可以直接提交

如果你不放心自己的程序,可以把%lld改成%I64d(I是大寫i)進行調試,這樣就不會出錯了

但是切記

提交到洛谷上的時候一定要寫%lld!!!!!!

否則全部WA而不是RE

切記切記

(ps:cena評測系統也是%lld)

我的代碼基本是由函數構成的

寫法比較通俗易懂

大家可以參考一下

再教大家一個小技巧:

如果你想要大批量的吧int改為long long int 的話

可以使#define 語句

然後用查找替換功能

註意查找的時候 查找的是 int+空格

否則你的printf會變得非常美觀(手動滑稽)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define lglg long long int
 5 using namespace std;
 6 const lglg MAXN=200001;
 7 lglg n,m;
 8 lglg ans=0;
 9 struct node
10 {
11     lglg l,r,w,f;
12 }tree[MAXN*4];
13 inline void updata(lglg k)
14 {
15     tree[k].w=tree[k*2].w+tree[k*2+1].w;
16 }
17 inline void build(lglg k,lglg ll,lglg rr)
18 {
19     tree[k].l=ll;tree[k].r=rr;
20     if(tree[k].l==tree[k].r)
21     {
22         scanf("%lld",&tree[k].w);
23         return ;
24     }
25     lglg m=(ll+rr)/2;
26     build(k*2,ll,m);
27     build(k*2+1,m+1,rr);
28     updata(k);
29 }
30 inline void down(lglg k)
31 {
32     tree[k*2].f+=tree[k].f;
33     tree[k*2+1].f+=tree[k].f;
34     tree[k*2].w+=(tree[k*2].r-tree[k*2].l+1)*tree[k].f;
35     tree[k*2+1].w+=(tree[k*2+1].r-tree[k*2+1].l+1)*tree[k].f;
36     tree[k].f=0;
37 }
38 inline void interval_change(lglg k,lglg ll,lglg rr,lglg v)
39 {
40     if(tree[k].l>=ll&&tree[k].r<=rr)
41     {
42         tree[k].w+=(tree[k].r-tree[k].l+1)*v;
43         tree[k].f+=v;
44         return ;
45     }
46     if(tree[k].f)   down(k);
47     lglg m=(tree[k].l+tree[k].r)/2;
48     if(ll<=m)    interval_change(k*2,ll,rr,v);
49     if(rr>m)     interval_change(k*2+1,ll,rr,v);
50     updata(k);
51 }
52 inline void interval_ask(lglg k,lglg ll,lglg rr)
53 {
54     if(tree[k].l>=ll&&tree[k].r<=rr)
55     {
56         ans+=tree[k].w;
57         return ;
58     }
59     if(tree[k].f)    down(k);
60     lglg m=(tree[k].l+tree[k].r)/2;
61     if(ll<=m)
62         interval_ask(k*2,ll,rr);
63     if(rr>m)
64         interval_ask(k*2+1,ll,rr);
65 }
66 int main()
67 {
68     scanf("%lld",&n);
69     scanf("%lld",&m);
70     build(1,1,n);
71     while(m--)
72     {
73         lglg how;
74         scanf("%lld",&how);
75         if(how==1)//區間增加 
76         {
77             lglg x,y,v;
78             scanf("%lld%lld%lld",&x,&y,&v);
79             interval_change(1,x,y,v);
80         }
81         else//區間求和 
82         {
83             lglg x,y;
84             ans=0;
85             scanf("%lld%lld",&x,&y);
86             interval_ask(1,x,y);
87             printf("%lld\n",ans);
88         }
89     }
90     return 0;
91 }

P3372 【模板】線段樹 1