最近做了不少樹狀陣列的題目,不得不感嘆,這真是乙個優美的資料結構。起碼可以簡潔高效地求出陣列字首和。
最近常常碰到的是求一段區間內大於或小於某個數的個數。
如果數字範圍較大,但不要求修改的話,可以用樹狀陣列存離散化後的數的大小。
比如 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...