敵兵布陣
Description
C國的死對頭A國這段時間正在進行軍事演習,所以C國間諜頭子Derek和他手下Tidy又開始忙乎了。A國在海岸線沿直線布置了N個工兵營地,Derek和Tidy的任務就是要監視這些工兵營地的活動情況。由於采取了某種先進的監測手段,所以每個工兵營地的人數C國都掌握的一清二楚,每個工兵營地的人數都有可能發生變動,可能增加或減少若干人手,但這些都逃不過C國的監視。Input
第一行一個整數T,表示有T組數據。Output
對第i組數據,首先輸出“Case i:”和回車,Sample Input
1 10 1 2 3 4 5 6 7 8 9 10 Query 1 3 Add 3 6 Query 2 7 Sub 10 2 Add 6 3 Query 3 10 End
Sample Output
Case 1: 6 33 59
題意:一維線性的直線上,排列著n個兵營,初始每個兵營有固定的人數,有兩個操作:一個是添加,把某個兵營增加人數d;二是詢問,求某兩個兵營之間所有兵營的總人數之和。
解題思路:這個題以前用樹狀數組寫過,是很基礎的樹狀數組模板題,也是很基礎的線段樹的題目,因為在內存允許的情況下,能用樹狀數組切的題,線段樹都能切,線段樹還有好多樹狀數組搞不定的功能,很神奇哦~~~只不過,線段樹寫著比樹狀數組復雜多了,樹狀數組最大的優點就是簡單,所以能用樹狀數組切的題,就不要用線段樹做!
但是,今天用線段樹重切這題,是因為要搞線段樹了,先從基本的搞起,是為了學習線段樹才寫的。。。
樹狀數組解法 HDU 1166 敵兵布陣 (樹狀數組)
關於線段樹的基本內容,詳見 線段樹之入門篇
AC代碼:
#include#define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 55555; int sum[maxn<<2]; void PushUP(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void build(int l,int r,int rt) { //建樹 if (l == r) { scanf(%d,&sum[rt]); return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUP(rt); } void update(int p,int add,int l,int r,int rt) { //更新 if (l == r) { sum[rt] += add; return ; } int m = (l + r) >> 1; if (p <= m) update(p , add , lson); else update(p , add , rson); PushUP(rt); } int query(int L,int R,int l,int r,int rt) { //詢問 if (L <= l && r <= R) { return sum[rt]; } int m = (l + r) >> 1; int ret = 0; if (L <= m) ret += query(L , R , lson); if (R > m) ret += query(L , R , rson); return ret; } int main() { int T , n; scanf(%d,&T); for (int cas = 1 ; cas <= T ; cas ++) { printf(Case %d: ,cas); scanf(%d,&n); build(1 , n , 1); char op[10]; while (scanf(%s,op)) { if (op[0] == 'E') break; int a , b; scanf(%d%d,&a,&b); if (op[0] == 'Q') printf(%d ,query(a , b , 1 , n , 1)); else if (op[0] == 'S') update(a , -b , 1 , n , 1); else update(a , b , 1 , n , 1); } } return 0; }