pku2140任意區間第k小數-歸併樹

來源:互聯網
上載者:User

 

http://poj.org/problem?id=2104

 

題意:給你一個數組,求任意區間[i, j]的第k小的數。。。(沒有修改)

 

 

分析:

PS:進階資料結構真難學。。顯然我是創造不出來這些進階資料結構的了。歸併樹。。網上到處學習,網上各種解釋,都不怎麼看得懂。。。主要參考了http://blog.sina.com.cn/s/blog_5f5353cc0100kh6b.html學習了代碼。。。orz,弄代碼才懂的。。。

 http://yueyue1105.blog.163.com/blog/static/431117682010716111425892/這個地方講得比較清楚,介紹了歸併樹和劃分樹。。。

 

 

簡單解釋:二分+歸併排序+線段樹+二分

首先建樹:按照歸併排序的過程,先走到底,然後將該層(deep)[l...r]歸併後得到的資料存到seq[deep][l...r]中去,則這一小段始終是有序的。。。。可以想象,最上層是排好序的數組,所有葉子節點組合起來就是原數組。。。

查詢分三個步驟:1是在最上層二分選取一個元素key,查詢key在[l, r]中大於幾個數num,取得一個最小的num>=k的那個,則為所求,通過線段樹去查詢key在[l, r]中大於幾個數num,到了符合的區間後就可以通過二分來求得其在本區間大於幾個數。。。貌似說不清楚了。。

 

歸併樹代碼:

#include<iostream>using namespace std;const int N=100010;const int DEEP=20;int seq[DEEP][N]; //歸併樹int a[N], n, m;struct node{int l, r, mid;} tree[N*4]; //線段樹//線段樹+歸併樹一起建了,實際上二者的過程一樣。。void build(int l, int r, int p, int deep){tree[p].l = l;tree[p].r = r;tree[p].mid = (l+r)>>1;if(l==r){seq[deep][l] = a[l];return;}build(l, tree[p].mid, p*2, deep+1);build(tree[p].mid+1, r, p*2+1, deep+1);//歸併過程int i, j, k;for(i=l, j=tree[p].mid+1, k=l; i<=tree[p].mid && j<=r; ){if(seq[deep+1][i]>seq[deep+1][j])seq[deep][k++] = seq[deep+1][j++];elseseq[deep][k++] = seq[deep+1][i++];}while(i<=tree[p].mid)seq[deep][k++] = seq[deep+1][i++];while(j<=r)seq[deep][k++] = seq[deep+1][j++];}//通過二分枚舉,返回key在本區間大於多少個數//注意:任何一個通過線段樹最終到達的區間一定是已經排好序了的,所以可以通過二分求int counthelp(int l, int r, int p, int key, int deep){int mid;while(l<=r){mid = (l+r)>>1;if(seq[deep][mid]<key)l = mid+1;elser = mid-1;}return r-tree[p].l+1;}//返回key在[l, r]總區間內大於幾個數int count(int l, int r, int p, int key, int deep){if(tree[p].l==l && tree[p].r==r){return counthelp(l, r, p, key, deep);}if(r<=tree[p].mid)return count(l, r, p*2, key, deep+1);else if(l>tree[p].mid)return count(l, r, p*2+1, key, deep+1);else{return count(l, tree[p].mid, p*2, key, deep+1)+count(tree[p].mid+1, r, p*2+1, key, deep+1);}}//返回在通過二分枚舉後得到的結果。。。int query(int ll, int rr, int cnt){int mid, tmp;int l = 1;int r = n;while(l<=r){mid = (l+r)>>1;tmp = count(ll, rr, 1, seq[1][mid], 1); if(tmp>=cnt)r = mid-1;elsel = mid+1;}return seq[1][l-1];}int main(){int i, x, y, cnt;while(scanf("%d %d", &n, &m)!=EOF){for(i=1; i<=n; i++)scanf("%d", &a[i]);build(1, n, 1, 1);while(m--){scanf("%d%d%d", &x, &y, &cnt);printf("%d\n", query(x, y, cnt));}}return 0;}

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.