1. 程式人生 > 其它 >os:firewall-cmd埠管理(轉載)

os:firewall-cmd埠管理(轉載)

時間複雜度: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;
}