思維難度好大的題…
我們思考如何對於a[i
]a[i]
a[i]
來說,有多少對合法的(a[
i],a
[j])
(j(a[i],a[j])(j(a
[i],
a[j])(j
.我們可以預處理出所有a[i]的因數和倍數,並儲存來乙個陣列內;當求解a[i]時,我們就把所有位置小於等於i(不計算大於是為了避免重複計算)的所有a[i
]a[i]
a[i]
的因數或倍數都存進樹狀陣列裡。如果要求解區間[l,
r][l,r]
[l,r
],只要ask
(r)−
ask(
l)ask(r)-ask(l)
ask(r)
−ask
(l)即可。
同理,我們需要[l,
r][l,r]
[l,r
]中所有的對數,只需要ask
(r)−
ask(
l)ask(r)-ask(l)
ask(r)
−ask
(l)即可;因為每乙個數事實上是單獨計算的,僅僅利用樹狀陣列來維護乙個整體累加。這樣,我們就能夠在列舉i的時候求解任意q[k
]=rq[k]=r
q[k]=r
的答案了。
最後,我們只要將每乙個詢問離線一下,按照右端點從左到右排序即可。
**如下:
#include
using
namespace std;
int n,m;
int a[
300000];
int pos[
300000];
int ans[
300000];
vector <
int> big[
300000];
vector <
int> sma[
300000];
struct node };
node q[
300000];
struct tree
intask
(int x)
} tree;
inline
intread
(void
)void
get(
int x)
return;}
intmain
(void
)for
(int j=
0;jsize()
;++j)
while
(q[now]
.r == i && now <= m)
ans[q[now]
.id]
= tree.
ask(q[now]
.r)-tree.
ask(q[now]
.l-1
), now ++;}
for(
int i=
1;i<=m;
++i)
printf
("%d\n"
, ans[i]);
return0;
}
樹狀陣列1 樹狀陣列入門
仔細看一下,發現tree的每乙個節點的高度並不是隨意的,而是由它轉成二進位制之後末尾連續零的數量決定的,連續零的數量加1,就是高度,例如 3 11 零的數量為0,加1等於1,所以它的高度就是1 6 110 零的數量為1,加1等於2,所以它的高度就是2 8 1000 零的數量為3,加1等於4,所以它的...
樹狀陣列 瞎bb 樹狀陣列
樹狀陣列是乙個利用一維陣列和位運算組成的求解區間問題的高效資料結構,其構造如圖所示 首先,我們要用它解決單點修改 區間查詢的操作。根據這張圖我們建立乙個陣列bit,下標就是圖中顯示的十進位制數。bit i 就表示了圖中所示的一段區間的和,例如bit 6 sum 5,6 bit 4 sum 1,4 下...
樹狀陣列 二維樹狀陣列模板
樹狀陣列模板 int lowbit int x int add int x,int val int que int x 模板題 題解 include include include using namespace std int c 300000 rank 300000 int n int lowb...