樹狀陣列 牛客挑戰賽15D 數字串

2021-08-19 22:14:16 字數 1278 閱讀 9512

最近做了不少樹狀陣列的題目,不得不感嘆,這真是乙個優美的資料結構。起碼可以簡潔高效地求出陣列字首和。

最近常常碰到的是求一段區間內大於或小於某個數的個數。

如果數字範圍較大,但不要求修改的話,可以用樹狀陣列存離散化後的數的大小。

比如 1 2 4 4 6 7,離散化 1 2 3 3 4 5,統計個數 0 1 1 2 1 1

每新增乙個新數,都看看有沒有當前位置結束的區間,用樹狀陣列求一下區間內小於某數的和。

當然,這樣比較繁瑣,還要考慮每個區間的起始位置,如果會持久化線段樹就很方便。

如果數字範圍比較小,比如這道題,那麼有修改也不怕,有幾個數就開幾個樹狀陣列,存數的位置。

比如1 2 3 3 4 5

1號陣列:1 0 0 0 0 0

2號陣列:0 1 0 0 0 0

3號陣列:0 0 1 1 0 0

4號陣列:0 0 0 0 1 0

5號陣列:0 0 0 0 0 1

需要修改的時候對對應數字的樹狀陣列修改。

需要統計的時候統計每乙個需要的樹狀陣列。

乙個只含數字的字串,q次操作,每次操作將第i位數字改為x,每次操作後,統計長度在[l, r]之間且首數字大於尾數字的子串的個數。

思路:

每乙個字元對答案的貢獻是它前 r 到前 l 內大於它的數字個數

和後 l 到後 r 內小於它的元素個數

插入的時候按值的大小插入到各自的樹狀陣列中,注意只當作尾插入就好,不然會重複。

修改時先減去原字元對答案的貢獻,再加上新的

#include

using

namespace

std;

typedef

long

long ll;

const

int maxn = 100010;

char c[maxn];

int a[maxn];

int n,q,l,r,p,x;

int t[10][maxn];

void upd(int x,int p,int d)

return res;

}ll qdown(int p)

return res;

}ll qup(int p)

return res;

}int main()

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

while(q--)

return

0;}

很美,是吧

Wannafly挑戰賽15 D 數字串 區間逆序對

乙個只含數字的字串,q次操作,每次操作將第i位數字改為x,每次操作後,統計長度在 l,r 之間且首數字大於尾數字的子串的個數。第一行乙個只含數字的字串 第二行3個整數q,l,r 接下來q行,每行兩個整數i,x。輸出q行,每行乙個整數,表示長度在 l,r 之間且首數字大於尾數字的子串的個數。示例1 5...

Wannafly挑戰賽15 D 數字串 線段樹

乙個只含數字的字串,q次操作,每次操作將第i位數字改為x,每次操作後,統計長度在 l,r 之間且首數字大於尾數字的子串的個數。第一行乙個只含數字的字串 第二行3個整數q,l,r 接下來q行,每行兩個整數i,x。輸出q行,每行乙個整數,表示長度在 l,r 之間且首數字大於尾數字的子串的個數。題解 更改...

牛客挑戰賽 56 D

給出乙個排列 p 求滿足條件的三元組 i,j,k 個數 n le 10 5 莫比烏斯反演 感覺大半年沒有複習過莫比烏斯反演了,於是這個題直接幫我複習了一下 真 訓練 考慮固定 j 計算貢獻,然後就是求字首和字尾中 gcd p i,x k 的個數了,記出現之前每個數出現次數為 cnt 那麼貢獻為 be...