樹狀陣列學習 題集

2021-09-11 20:07:59 字數 3611 閱讀 3495

舉個例子,有幾個數可以通過lowbit產生0100呢?0001--lowbit-->0010-->lowbit-->0011-->lowbit-->0100,有三個數可以通過lowbit產生0100,加上它本身,總共維護了2^2個數的和。比如5(0101)沒有數可以通過lowbit產生,所以維護它本身乙個。6(0110)可以有5(0101)lowbit產生,所以維護兩個。

大家有沒有發現要通過lowbit產生x1xx(x代表未知數),只能通過x0xx+lowbit產生,而後面的xx可以是01,10,11,2^k怎麼得出來該明白了吧!以下就是add(i,x)函式了

void add(int i,int x)

}

我們可以看到每個以ci維護的只是一段區間和,那我們求字首和只需找到對應的幾個ci即可。

比如我們要求前6(0110)個數的字首和為c6 + c4。c6維護的是a[5]+a[6]。現在只需x -= lowbit(x)。0110-0010=0100。而0100永遠也不可能lowbit到0110(上面說過了),所以0110和0100維護的區間是完全沒有關係的。0100維護的是a[1]+a[2]+a[3]+a[4]。正好找到字首和。

為什麼這樣可行呢?0110後面維護2^1個數,0100維護的是2^2個數。加起來正好是6 = 0010 + 0100。再比如11100 = 00100 + 01000 + 10000,而這些數都可以通過lowbit產生,通過維護的個數和,我們很容易能夠驗證這樣的方法可行的。一下是求和函式。

int sum(int i)

return s;

}

#include using namespace std;

typedef long long ll;

int const n = 500000 + 10;

int d[n],n,m;

int lowbit(int x)

ll sum(int i)

return sum;

}void add(int i,int x)

}int main()

while(m--)

}

#include using namespace std;

int const n = 500000 + 10;

int n,m,d[n],a[n];

int lowbit(int x)

void add(int i,int x)

}int sum(int i)

return s;

}int main()else

} return 0;

}

#include using namespace std;

int const n = 200000 + 10;

typedef long long ll;

ll c1[n],c2[n],a[n];

int n,m,k;

ll lowbit(ll x)

void add(ll c[n],ll i,ll x)

}ll getsum(ll c[n],ll i)

return s;

}int main()

}

左右括號的方法。在乙個區間內種樹,相當於加一對括號。用樹狀陣列維護從起始到這個位置的左右括號的數量。區間內有左括號那麼一定有這一種型別的樹,只有離開了對應的右括號這種樹才沒有了。所以為了統計區間[x,y]內的樹種類,只需把y左邊左括號的個數-(x-1)左邊右括號的個數即可。

#include using namespace std;

int const n = 50000 + 10;

int c1[n],c2[n];

int n,m;

int lowbit(int x)

void add(int c[n],int i)

}int getsum(int c[n],int i)

return s;

}int main()else

}}

#include #include #include #include #include using namespace std;

int const n = 1000 + 10;

int n,m,c[n][n];

int lowbit(int x)

void add(int x,int y)

int sum(int x,int y)

int main()else

} }return 0;

}

這是一道樹狀陣列求逆序數的經典題目。注意要離散化,最後要開long long。

#include #include #include #include #include using namespace std;

typedef long long ll;

int const n = 500000 + 10;

int a[n],n,d[n];

ll ans;

vectorv;

int lowbit(int x)

void add(int i,int x)

}int sum(int i)

return s;

}int main()

sort(v.begin(),v.end());

v.erase(unique(v.begin(),v.end()),v.end());

memset(d,0,sizeof(d));

ans = 0;

for(int i=1;i<=n;i++)

printf("%lld\n",ans);

} return 0;

}

又是一道求逆序數的題目。先排序,x公升序,x相同y公升序。注意要long long,資料範圍不準確。

#include #include #include #include #include using namespace std;

int const n = 1000 + 10;

typedef long long ll;

int n,m,k,d[n];

ll ans;

struct road

}road[n*n];

int lowbit(int x)

void add(int i,int x)

}int sum(int i)

return s;

}int main()

void add(int i,int x)

}int sum(int i)

return s;

}int main()

for(int i=0;i<=n-1;i++) printf("%d\n",num[i]);

return 0;

}

pta 習題集 5 15 陣列迴圈左移

本題要求實現乙個對陣列進行迴圈左移的簡單函式 乙個陣列a a中存有n n 0 0 個整數,在不允許使用另外陣列的前提下,將每個整數迴圈向左移m m 0 0 個位置,即將a a中的資料由 a0a1 an 1a 0 a 1 a n 1 變換為 am an 1a0a1 am 1a m a n 1 a 0 ...

Python習題集(四)

如果乙個 3 位數等於其各位數字的立方和,則稱這個數為水仙花數。例如 153 1 3 5 3 3 3,因此 153 就是乙個水仙花數 那麼問題來了,求1000以內的水仙花數 3位數 int轉字串序列,獲取到每一位數 呼叫math.pow函式求立方和 三個數字立方和相加 lists for i in ...

Python習題集(十二)

請寫乙個函式find odd,引數是1個列表,請返回該列表 現奇數次的元素 比如 find odd 1,1,2,2,5,2,4,4,1,2,5 1 find odd 20,1,1,2,2,3,3,5,5,4,20,4,5 5 find odd 10 10 迴圈列表 呼叫列表內建統計函式計算當前元素出...