os:firewall-cmd埠管理(轉載)
阿新 • • 發佈:2022-03-26
時間複雜度:logn
樹狀陣列的唯一作用:快速求字首和並支援單點修改(增加一個數,或者加當前數相反數,再加自己想修改的數,實現數值替換)
區間修改,單點查詢題-----需要將原題目差分
區間修改,區間查詢。
樹狀陣列公式(最好記憶):
C[x]=(x-lowbit(x),x] 區間內數的和
lowbit(x)=x & -x = 2^k 返回最後1的位置
x位置的父節點:x+lowbit(x)
操作:
1.某位置加上一個數 ,從該節點向上一層層的父節點全加上這個數 o(logn)
2.求某一個字首和 C[x]+C[x-lowbit(x)] ....遞迴呼叫 o(logn)
裸題模板:
https://www.acwing.com/problem/content/1266/
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 1e5+10; int n,m; int a[N],tr[N]; int lowbit(int x) { return x & -x; } void update(int x,int v){ for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=v;//x+lowbit(x)為父節點位置,一直到最高層每個結點都加上這個數。 } int query(int x){ int res=0; for(int i=x;i;i-=lowbit(i)) res+=tr[i]; //(x-lowbit(x),x] 區間內的和即為字首和 return res; } int main() { cin>>n>>m; for(int i=1;i<=n;i++){ scanf("%d", &a[i]); } //初始化 for(int i=1;i<=n;i++){ update(i,a[i]); } while (m -- ){ int oper,a,b; scanf("%d%d%d",&oper,&a,&b); if(oper==0){ cout<<query(b)-query(a-1)<<endl; }else{ update(a,b); } } return 0; }