1. 程式人生 > >[Codevs] 1080 線段樹練習

[Codevs] 1080 線段樹練習

細節 pac htm .cn cti row amp 動態 cnblogs

1080 線段樹練習

時間限制: 1 s 空間限制: 128000 KB 題目等級 : 鉆石 Diamond 題目描述 Description

一行N個方格,開始每個格子裏都有一個整數。現在動態地提出一些問題和修改:提問的形式是求某一個特定的子區間[a,b]中所有元素的和;修改的規則是指定某一個格子x,加上或者減去一個特定的值A。現在要求你能對每個提問作出正確的回答。1≤N<100000,,提問和修改的總數m<10000條。

輸入描述 Input Description

輸入文件第一行為一個整數N,接下來是n行n個整數,表示格子中原來的整數。接下一個正整數m,再接下來有m行,表示m個詢問,第一個整數表示詢問代號,詢問代號1表示增加,後面的兩個數x和A表示給位置X上的數值增加A,詢問代號2表示區間求和,後面兩個整數表示a和b,表示要求[a,b]之間的區間和。

輸出描述 Output Description

共m行,每個整數

樣例輸入 Sample Input

6

4 5 6 2 1 3

4

1 3 5

2 1 4

1 1 9

2 2 6

樣例輸出 Sample Output

22

22

數據範圍及提示 Data Size & Hint

1≤N≤100000, m≤10000 。

分析 Analysis

分塊!

主要是細節部分千萬要寫好。

相關解釋:

[Codevs] 1081 線段樹練習 2 ----“分塊!”

代碼 Code

技術分享
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #define maxn 1000000
 5 using namespace std;
 6 
 7 int block[maxn],size,arr[maxn],sum[maxn],n,q,a,b,c;
 8 
 9 int query(int a,int b){
10     int ans = 0;
11     for(int i = a;i <= min(block[a]*size-1
,b);i++) 12 ans += arr[i]; 13 if(block[a] != block[b]) 14 for(int i = (block[b]-1)*size;i <= b;i++) 15 ans += arr[i]; 16 for(int i = block[a]+1;i < block[b];i++) 17 ans += sum[i]; 18 return ans; 19 } 20 21 int main(){ 22 scanf("%d",&n); 23 size = (int)sqrt(n)+1; 24 for(int i = 0;i < n;i++) block[i] = i/size+1; 25 for(int i = 0;i < n;i++) scanf("%d",&arr[i]); 26 for(int i = 0;i < n;i++) sum[block[i]] += arr[i]; 27 scanf("%d",&q); 28 for(int i = 0;i < q;i++){ 29 scanf("%d%d%d",&a,&b,&c); 30 if(a%2) arr[b-1] += c,sum[block[b-1]] += c; 31 else printf("%d\n",query(b-1,c-1)); 32 } 33 34 // printf("#size: %d\n",size); 35 // for(int i = 0;i < n;i++) printf("#%d: block%d\n",i,block[i]); 36 // for(int i = 1;i <= n;i++) printf("#%d: ->%d\n",i,sum[i]); 37 38 return 0; 39 }
分塊!

[Codevs] 1080 線段樹練習