1082 線段樹練習 3
時間限制: 3 s
空間限制: 128000 KB
題目等級 : 大師 Master
題目描述 Description
給你N個數,有兩種操作:
1:給區間[a,b]的所有數增加X
2:詢問區間[a,b]的數的和。
輸入描述
Input Description
第一行一個正整數n,接下來n行n個整數,
再接下來一個正整數Q,每行表示操作的個數,
如果第一個數是1,後接3個正整數,
表示在區間[a,b]內每個數增加X,如果是2,
表示操作2詢問區間[a,b]的和是多少。
pascal選手請不要使用readln讀入
輸出描述
Output Description
對於每個詢問輸出一行一個答案
樣例輸入
Sample Input
3
1
2
3
2
1 2 3 2
2 2 3
樣例輸出
Sample Output
9
資料範圍及提示
Data Size & Hint
資料範圍
1<=n<=200000
1<=q<=200000
分類標籤 Tags 點此展開
在這裡提醒大家一點
如果你用的是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 build(1,1,n); 70 scanf("%lld",&m); 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 }