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的線段樹 大小是數字的個數 記錄該字...