因為樹狀陣列用得比較少,所以今天總結一下常見用法。(順便貼一些板)
首先上樹狀陣列的定義:設原陣列為a,樹狀陣列為c,那麼c[i]=a[i-2^k+1]+a[i-2^k+2]……+a[i]。其中k為i的二進位制狀態下最後面連續的0的個數。
然後我們就可以得出樹狀陣列的修改和查詢操作了。
下面貼一下查詢和修改的板:
int find(int x)
return s;
}
int change(int x,int y)
}
樹狀陣列的基本操作就在上面了,下面講一下一些常見的問題。
1、單點修改+區間查詢
這個上面已經講過了
2、區間修改+單點查詢
這乙個我們要用到差分思想:設b[i]=a[i]-b[i-1],而c維護的是b的和而不是a的和,那麼區間修改x~y的時候我們就只需要修改x和y+1即可。
**如下:
#include#include#include#define maxn 500010
int a[maxn],c[maxn],n,m,x,y,k,type;
int find(int x)
return s;
}int change(int x,int y)
}int main()
else
m--;
}}
3、區間修改+區間查詢
這乙個我們還是要用到差分思想,有上面的問題我們的到a[x]=b[1]+b[2]...+b[x],那麼我們就有
a[1]+a[2]+a[3]...+a[x]
=b[1]+(b[1]+b[2])+(b[1]+b[2]+b[3])+...+(b[1]+b[2]...+b[x])
=b[1]*x+b[2]*(x-1)+b[3]*(x-2)+...+b[x]*1
=x*(b[1]+b[2]+...+b[x])-(b[1]*0+b[2]*1+b[3]*2+...+b[x]*(x-1))
到這裡就十分清晰了。我們只需用兩個樹狀陣列,分別維護b[i]的和以及b[i]*(i-1)就可以了。
下面貼一下**:
#include#include#include#define ll long long
#define maxn 100010
ll a[maxn],c1[maxn],c2[maxn],n,m,x,y,k;
char type;
ll find1(ll x)
return s;
}ll find2(ll x)
return s;
}int change1(ll x,ll y)
return 0;
}int change2(ll x,ll y)
return 0;
}ll sum(ll x)
int main()
else
m--;
}return 0;
}
樹狀陣列的常數很小,**很短,但是處理的範圍窄。在做一些有關求和問題的時候不妨用一用。 樹狀陣列總結
樹狀陣列的基本知識已經被各種大牛和菜鳥講到爛了,我就不多說了,下面給出基本操作的 假定原陣列為a 1.n 樹狀陣列b 1.n 考慮靈活性的需要,使用int a傳陣列。define lowbit x x x int sum int a,int x void update int a,int x,int...
樹狀陣列總結
樹狀陣列是對乙個陣列改變某個元素和求和比較實用的資料結構。兩中操作都是o logn 在解題過程中,我們有時需要維護乙個陣列的字首和s i a 1 a 2 a i 但是不難發現,如果我們修改了任意乙個a i s i s i 1 s n 都會發生變化。可以說,每次修改a i 後,調整字首和s在最壞情況下...
樹狀陣列總結
今天學習了一下樹狀陣列,做乙個簡單總結。樹狀陣列可分為兩種操作,1 修改單個點,統計區間和 一般為 向上修改 update1 向下統計 sum1 2 修改區間,統計單個點 一般為向下修改 update2 向上統計 sum2 主要模板如下 int c n int lowbit int x 用於確定區間...