標籤:輸出 問題: alt 輸入 ora 區間 pre 輸入輸出 class
題目描述
如題,已知一個數列,你需要進行下面兩種操作:
1.將某一個數加上x
2.求出某區間每一個數的和
輸入輸出格式
輸入格式:
第一行包含兩個整數N、M,分別表示該數列數位個數和操作的總個數。
第二行包含N個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。
接下來M行每行包含3個整數,表示一個操作,具體如下:
操作1: 格式:1 x k 含義:將第x個數加上k
操作2: 格式:2 x y 含義:輸出區間[x,y]內每個數的和
輸出格式:
輸出包含若干行整數,即為所有操作2的結果。
輸入輸出範例輸入範例
5 51 5 4 2 31 1 32 2 51 3 -11 4 22 1 4
輸出範例
1416
說明
時空限制:1000ms,128M
資料規模:
對於30%的資料:N<=8,M<=10
對於70%的資料:N<=10000,M<=10000
對於100%的資料:N<=500000,M<=500000
範例說明:
故輸出結果14、16
講解:
為什麼用樹狀數組?先問幾個問題:
1. 給一串數列,幾次操作,每次操作把要求的數加上某個數(也就是對這個數字修改)
我們用一個數組,O(1) 可以做到
2. 給一串數列,幾次操作,每次操作把要求的區間和求出
這也簡單,利用首碼和做完預先處理,O(1) 也可以做到
但,既要修改,又要求首碼和呢?
還按上述做法,我們每修改一次,首碼和就要重新更新,多次操作下來,將非常耗時間
於是,一個神奇的做法出現——樹狀數組
它好在一個 lowbit 操作,再修改單點的同時,以一種神奇的方法,快速地更新了區間和
具體講解參考教材
代碼
#include<stdio.h>const int Mx=500001;int a[Mx],c[Mx];int n,m;int lowbit(int x){ return x&-x;}void add(int x,int tx){ for(int i=x;i<=n;i+=lowbit(i)){ c[i]+=tx; }}int ask(int x){ int tot=0; for(int i=x;i;i-=lowbit(i)) tot+=c[i]; return tot; }int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ scanf("%d",&a[i]); add(i,a[i]); } while(m--){ int kiss; scanf("%d",&kiss); if(kiss==1){ int kis,jia; scanf("%d%d",&kis,&jia); add(kis,jia); } else if(kiss==2){ int l,r; scanf("%d%d",&l,&r); printf("%d\n",ask(r)-ask(l-1)); } } return 0;}
樹狀數組【模板 1】