題目【模板】樹狀陣列1:
樹狀陣列和線段樹差不多,可以處理區間操作,但是處理不了太複雜的區間問題。,不過**比線段樹簡潔很多很多!!!時間複雜度都為o(logn)。
例如,區間[1,8]儲存方式如下:
1 tree[1]=num[1];//從注釋可以看出儲存方式和二進位制有關係。001---001
2 tree[2]=num[2]+num[1];//
010---010 001
3 tree[3]=num[3];//
011---011
4 tree[4]=num[4]+num[3]+num[2]+num[1];//
100---100 011 010 001
5 tree[5]=num[5];//
101---101
6 tree[6]=num[6]+num[5];//
110---110 101
7 tree[7]=num[7];//
111---111
8 tree[8]=num[8]+num[7]+num[6]+num[5]+num[4]+num[3]+num[2]+num[1];///
1000---1000 0111 0110 0101 0100 0011 0010 0001
遞推可得,當第x個數加上k時,tree[x]要加k,然後tree[x+x只剩最低位的1]也要加上x,迴圈往復。
根據負數在計算機中用補碼儲存可得k & -k即為x只剩最低位的1。
如7&-7
7用二進位制表示為111,-7補碼形式為001,111&001得001,所以7只剩最低位的1為001.
ac**:
#include#includeview code#include
#define maxn 500010typedef
long
long
ll;using
namespace
std;
intn;
ll tree[maxn
<< 2
];int lowbit(int
k) void add(int
x, ll k)
}ll sum(
intx)
return
ans;
}int
main()
while (m--)
else
}return0;
}
o(∩_∩)o哈哈~
補充一道區間加k的操作。
用差分思想和樹狀陣列結合。
設陣列a=,那麼差分陣列b=
也就是說b[i]=a[i]-a[i-1];(a[0]=0;),則遞推可得:a[i]=b[1]+....+b[i]
所以對區間[x,y]進行修改,只用修改b[x]與b[y+1]:
b[x]=b[x]+k;b[y+1]=b[y+1]-k;
#include#includeview code#include
#define maxn 500010typedef
long
long
ll;using
namespace
std;
intn,a[maxn];
ll tree[maxn
<< 2
];int lowbit(int
k) void add(int
x, ll k)
}ll sum(
intx)
return
ans;
}int
main()
while (m--)
else
}return0;
}
\(^o^)/~
一天一道演算法題 線段樹
題目 模板 線段樹1 rmq問題 range minimum maximum query 和求區間和的問題可以用暴力法做,時間複雜度為o n 2 用在本題會超時,所以我們選擇線段樹做。線段樹是一種用於區間操作的資料結構,用二叉樹構造。如圖。線段樹的每個節點代表了乙個區間。防止超時,用了lazy標記。...
一天一道演算法題 5 24 遞迴
我們每一天都應該比昨天更強一點 觀察下列式子 12 12 1 12 6 2 12 4 3 12 3 4 12 3 2 2 12 2 6 12 2 3 2 12 2 2 3 對於給定的n 計算n公有多少種不同的分解式?1 include 2 using namespace std 34 int cnt...
一天一道演算法題 之動態規劃
最近做了幾道動態規劃題,發現了其中一些規律,認真覆盤一下。先來看幾道題。1 機械人走方格 有乙個xxy的網格,乙個機械人只能走格點且只能向右或向下走,要從左上角走到右下角。請設計乙個演算法,計算機械人有多少種走法。注意網格中有些障礙點是不能走的。給定乙個intmap c 中為vector 表示網格圖...