NYOJ 116 士兵殺敵(二)

2021-07-11 13:43:16 字數 1524 閱讀 7869

時間限制:

1000 ms  |  記憶體限制:

65535 kb

難度:5 描述

南將軍手下有n個士兵,分別編號1到n,這些士兵的殺敵數都是已知的。

小工是南將軍手下的軍師,南將軍經常想知道第m號到第n號士兵的總殺敵數,請你幫助小工來回答南將軍吧。

南將軍的某次詢問之後士兵i可能又殺敵q人,之後南將軍再詢問的時候,需要考慮到新增的殺敵數。

輸入

只有一組測試資料

第一行是兩個整數n,m,其中n表示士兵的個數(1

輸出對於每次查詢,輸出乙個整數r表示第m號士兵到第n號士兵的總殺敵數,每組輸出佔一行

樣例輸入

5 6

1 2 3 4 5

query 1 3

add 1 2

query 1 3

add 2 3

query 1 2

query 1 5

樣例輸出

688

20

分析:

在做這道題之前,先了解一下什麼是樹狀陣列:

樹狀陣列是乙個查詢和修改複雜度為log(n)的資料結構,主要用於查詢任意兩位之間的所有元素之和。

對於這個圖,令這棵樹的節點編號為c1,c2,c3 ....cn,令每個節點的值為這棵樹的值的總和,不難發現:

c[1] = a[1]; c[2] = a[1] + a[2]; c[3] = a[3]; c[4]  = a[1] + a[2] + a[3] + a[4];

c[5] = a[5]; c[6] = a[5] + a[6]; c[7] = a[7]; 

c[8] = a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8];

則c[i] = a[i - 2 ^ k + 1] + ... + a[i];其中k為i二進位制末尾0的個數 ;2 ^ k = i & (-i);

當我們修改a[i]的值時,可以從c[i]往根節點一路上溯,調整這條路上的所有c[ ]即可;

對於求數列的前n項和,只需要找到n以前的所有最大子樹,把其根節點的c加起來即可。

了解這些後,這道題就已經解出來了,**如下

#include#include#include#includeusing namespace std;

int a[1000010];

int n,m;

//求2^k

int lowbit(int x)

//修改操作

bool update(int i,int t)

}//查詢操作

int getsum(int i)//1 ~ i 的區間和

return sum;

}int main()

for(int i = 1;i <= m;i++)

}return 0;

}

NYOJ 116 士兵殺敵(二)

時間限制 1000 ms 記憶體限制 65535 kb難度 5 描述 南將軍手下有n個士兵,分別編號1到n,這些士兵的殺敵數都是已知的。小工是南將軍手下的軍師,南將軍經常想知道第m號到第n號士兵的總殺敵數,請你幫助小工來回答南將軍吧。南將軍的某次詢問之後士兵i可能又殺敵q人,之後南將軍再詢問的時候,...

NYOJ 116 士兵殺敵 二

樹狀陣列已經看了好幾天了,一直都是半懂半不懂,實在是忍無可忍了,今天晚上又看了看劉汝佳的 似乎明白了樹狀陣列到底是怎麼回事,果斷寫篇部落格,明天要把線段樹和字典樹給搞定,不能再肉了 樹狀陣列可以很方便的查詢任意區間內所有元素的和,還可以對樹進行修改,時間複雜度位log n 有兩個很重的陣列,a n ...

nyoj 116 士兵殺敵二

描述 南將軍手下有n個士兵,分別編號1到n,這些士兵的殺敵數都是已知的。小工是南將軍手下的軍師,南將軍經常想知道第m號到第n號士兵的總殺敵數,請你幫助小工來回答南將軍吧。南將軍的某次詢問之後士兵i可能又殺敵q人,之後南將軍再詢問的時候,需要考慮到新增的殺敵數。輸入 只有一組測試資料 第一行是兩個整數...