1. 程式人生 >實用技巧 >其它 >210929演算法日記:樹狀陣列

210929演算法日記:樹狀陣列


  • 今天剛剛開學提高課(什麼,你怎麼知道我的基礎課還有好多不會的)
  • 咳咳,實在是因為只刷題太枯燥了,所以想著刷累了看會兒課,這幾天老是聽別人講樹狀陣列和線段樹,發現自己也可以學,雖然我很菜,所以下面就對樹狀陣列做了一個小結
  • 樹狀陣列是幹什麼的,簡而言之就是平均複雜度的字首和
  • 字首和應該都知道吧,樹狀陣列能在o(logn)的複雜度內求到字首和,但是換回的是查詢更慢(也需要o(logn))字首和的查詢只需要o1
  • 但眾所周知,logn幾乎是常數,所以這波樹狀陣列完勝
  • 首先你得維護一個tree陣列,他代表的含義就是樹狀數組裡面的值
  • 每一個tree[x]代表[x - lowbit(x) + 1,x]的字首和,幹說有些難懂
  • 像下面這樣
x123456789
x的二進位制1101110010111011110001001
lowbit(x)121412181
tree[x]a1a1+a2a3a1+…+a4a5a5+a6a7a1+…+a8a9
  • 如何求字首和
  • sum[8] = tree[8]
  • sum[7] = tree[7]+tree[6]+tree[4]
  • sum[9] = tree[9]+tree[8]
  • 首先從7開始先加上tree[7]
  • 之後7-lowbit[7]=6加上tree[6]
  • 之後6-lowbit[6]=4加上tree[4]
  • 最後4-lowbit(4)=0結束
  • tree陣列的更新是同樣的
  • 二進位制解釋比如說x=10000,則x-1=01111
  • 第一段就是(01110~01111],a[15]
  • 第二段就是(01100~01110],a[13] ~ a[14]
  • 第三段就是(01000~01100],a[9] ~ a[12]
  • 第四段就是(00000~01000],a[1] ~ a[8]
  • 加起來再加a[16]就是tree[16]
  • 查詢操作: 觀察發現tree[x]=a[x]+tree[x-1]+tree[x-lowbit(x)-1]+…
  • 所以對應的迴圈遍歷是
int res=0;
for(int i=x;i;i-=lowbit(i)) res+=tree[i];
return res;
  • 修改操作: 再有就是修改了,我們發現000011100…直接影響到的點有且只有一個00010000…也就是x+lowbit(x)
  • 所以對應的迴圈遍歷是(如果a[x]要加c)
for(int i=x;i<=n;i+=lowbit(i)) tree[i]+=c;
  • 實現很簡單,應用也簡單,下面用一個例題來終結這篇部落格
  • link<-----樓蘭圖騰
#include<iostream>
#include<cstring>
using namespace std;
const int N=2e5+10;
int n,a[N],low[N],great[N];
typedef long long ll;
int tree[N];
int lowbit(int x)
{
    return x&-x;
}
void add(int x)
{
    for(int i=x;i<=n;i+=lowbit(i)) tree[i]+=1;
}
int sum(int x)
{
    int res=0;
    for(int i=x;i;i-=lowbit(i)) res+=tree[i];
    return res;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        int y=a[i];
        low[i]=sum(y-1);
        great[i]=sum(n)-sum(y);
        add(y);
    }
    memset(tree,0,sizeof tree);
    ll ans1=0,ans2=0;
    for(int i=n;i>=1;i--)
    {
        int y=a[i];
        ans1+=1ll*low[i]*(sum(y-1));
        ans2+=1ll*great[i]*(sum(n)-sum(y));
        add(y);
    }
    cout<<ans2<<' '<<ans1<<endl;
    return 0;
}
  • 210823完結