hdu2665 可持續化線段樹

2021-06-20 04:35:47 字數 2201 閱讀 1584

a的第一道可持續化線段樹。

我是看這個看懂的

可持續化線段樹,主要思想就是利用歷史資訊,減少時間和記憶體花銷。

比方有兩棵線段樹,但是他們只有乙個節點資訊不同。仔細一想,在這兩顆線段樹上,對應的 [l,r]節點  只有log(n)個節點不同。那麼,除了不同的節點,其他節點資訊,他們完全可以共用。

關於這題解法,我就複製別人的話了(  好懶啊 o(╯□╰)o )

考慮把權值離散化,然後用線段樹解決問題。

對於乙個詢問(x,y,k),如果已經把a[x]..a[y]建成了一顆線段樹,並維護區間和,顯然二分就可以了。

(怎麼二分? ...看左兒子有沒有k個然後遞迴 自己yy一下就出來了)

但是很遺憾我們沒辦法這麼搞...這還不如裸奔...

接下來思考乙個問題。

記t[x,y]為a[x]..a[y]建成的線段樹,那麼t[x,y]和t[1,x-1],t[1,y]有什麼關係?

對於t[x,y]中的乙個節點[l,r],我們一定可以在t[1,x-1]和t[1,y]中找到也代表[l,r]的對應節點。

考察這三個節點儲存的區間和的關係,馬上可以發現:

t[x,y]中任意節點[l,r]的區間和等於t[1,y]中對應節點的區間和減去t[1,x-1]中對應節點的區間和。

這就好辦多了,我們只需要把所有的t[1,x](1<=x<=n)建出來了就可以了。

......

發現什麼問題沒有? 空間和時間都不允許你建n棵線段樹的。

函式式資料結構的思想這時候派上用場了。

考察t[1,x]和t[1,x-1]——在t[1,x-1]加入a[x]就得到t[1,x]了。

單點修改的時候要改變資訊的節點的數量是o(logn)。

於是我們"大膽地重用以前的資訊",只新建這些節點,然後這些節點的左右兒子可以指向前一棵樹的節點。

最終的總節點個數是o(nlogn),預處理複雜度o(nlogn),回答每個詢問o(logn),常數還是有一點的。

//#pragma comment(linker, "/stack:102400000,102400000")

#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

#define mp(x,y) make_pair((x),(y))

#define pb(x) push_back(x)

typedef long long ll;

//typedef unsigned __int64 ull;

/* ****************** */

const int inf=1000111222;

const double inff=1e200;

const double eps=1e-8;

const ll mod=1000000007;

const int nn=100010;

const int mm=100010;

/* ****************** */

int a[nn],tf[nn],root[nn];

struct tr

tr[nn*20];

int cnt;

int build(int l,int r)

return id;

}void push_up(int r)

int update(int x,int pre,int l,int r)

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

if(x<=mid)

tr[id].ls=update(x,tr[pre].ls,l,mid);

else

tr[id].rs=update(x,tr[pre].rs,mid+1,r);

push_up(id);

return id;

}int query(int id1,int id2,int k,int l,int r)

int main()

sort(tf+1,tf+1+n);

tol=unique(tf+1,tf+1+n)-tf-1;

cnt=0;

root[0]=build(1,tol);

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

while(m--)

}return 0;

}

hdu2665 主席樹(可持久化線段樹)

題意 給定乙個陣列,每次查詢第l到r區間的第k大值 經過這題總算對可持久化線段樹有了些了解,我們開始先建一顆空樹,然後對於每次修改我們只會修改logn個點,我們可以新建logn個來避免每次都新建一顆線段樹導致的爆空間,對於這題來說我們線段樹中維護的是這個區間的點的個數,插入的時候按權值大小插入,對於...

hdu2665(主席樹模板題)

求區間第 k 小。參考這類題目做法挺多的,例如 劃分樹。這裡使用主席樹再寫一發,不得不說主席樹相比而言要好寫的多,比起普通線段樹,主席樹就是復用了線段樹共有的資訊。可持久化資料結構講究的就是復用共有的資訊,可持久化 trie 的思想也是差不多的。includeusing namespace std ...

hdu2665 主席樹模板題

題目 區間k大值,區間極值很容易想到線段樹,如果k是個位數的話,可以考慮開k個域的線段樹 滾 又稱可持久化線段樹,函式式線段樹 也許是上面兩個字看的太長,同時主席兩字給人一種不明覺厲的感覺,so,嘿嘿嘿 關於主席樹的講解可以看這 先離散化,對每個點i,建乙個1 i的線段樹 大小是數字的個數 記錄該字...