SPOJ DQUERY 離線樹狀陣列or主席樹

2021-08-08 22:39:18 字數 1510 閱讀 7824

給出n個數,問區間[l,r]中有多少不同的數。

經典題。

可以離線+樹狀陣列,離線儲存查詢,按照r排序,用last陣列儲存每個數最接近當前詢問r的位置。

也可以主席樹,從右到左建樹,pos儲存每個數字的當前最左位置,每次在新版本的線段樹中在當前位置+1,然後把舊版本中該樹的位置-1.

離線+樹狀陣列:

#include 

using

namespace

std;

const

int maxn = 1e6 + 10;

int n, q;

int bit[maxn];

void add(int x, int y)

}int sum(int x)

return res;

}struct node

} que[maxn];

int last[maxn], a[maxn], ans[maxn];

int main()

sort (que + 1, que + 1 + q);

for (int i = 1, j = 1; i <= q; i++)

ans[que[i].id] = sum(que[i].r) - sum(que[i].l - 1);

}for (int i = 1; i <= q; i++)

printf("%d\n", ans[i]);

return

0;}

主席樹:

#include 

using

namespace

std;

const

int maxn = 33333;

struct node ns[maxn * 40];

int rt[maxn * 2], ct;

void cpy(int& now, int old)

void build(int& now, int l, int r)

void update(int& now, int old, int l, int r, int x, int y)

int m = (l + r) >> 1;

if (x <= m) update(ns[now].ls, ns[old].ls, l, m, x, y);

else update(ns[now].rs, ns[old].rs, m + 1, r, x, y);

ns[now].sum = ns[ns[now].ls].sum + ns[ns[now].rs].sum;

}int query(int now, int old, int l, int r, int l, int r)

int pos[1000005], a[maxn];

int main()

int q;

scanf("%d", &q);

while (q--)

return

0;}

區間的關係的計數 HDU 4638 離線 樹狀陣列

題目大意 給你n個人,每個人都有乙個id,有m個詢問,每次詢問乙個區間 l,r 問該區間內部有多少的id是連續的 單獨的也算是乙個 思路 做了那麼多離線 樹狀陣列的題目,感覺這種東西就是乙個模板了,23333,反正都是定義右區間的。這題的關鍵難度就是如何定義id是連續的呢。我們每次往區間裡面放乙個數...

hdu 3333 離線 樹狀陣列

題目 題意 求乙個區間內不重複數字的和,例如1 1 1 3,區間 1,4 的和為4。分析 我們考慮每個查詢 l,r 現在要求的是這個區間裡不通數的和,所以我們在從左掃到右的過程中,可以用乙個資料結構儲存已經得到的不同的數,到右端點後,然後對區間裡不同的數求和,這樣就可以得到答案了。資料結構可以採用樹...

Binary Indexed Tree 樹狀陣列

做leetcode 做到meetingroomii的時候我知道不用線段樹或者樹狀陣列是不太好搞了。還是來學習一下吧。樹狀陣列算是線段樹的一種特殊情況 子集 所以樹狀陣列能解決的問題線段樹一定能做,但線段樹能做的樹狀陣列不一定能做。對乙個陣列進行如下操作 update i1,i2,operation ...