亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

【POJ 2104】K-th Number&主席樹詳解

2019-11-14 09:11:48
字體:
來源:轉載
供稿:網友

POJ 2104

題意

給定1到n的排列,每次詢問某一區間內的第k小值。

樣例輸入

7 3 1 5 2 6 3 7 4 2 5 3 4 4 1 1 7 3

樣例輸出

5 6 3


主席樹介紹

可持久化線段樹,函數式線段樹。 有點抽象,能夠理解但還不是很熟練,代碼不長,但是非常簡練,有很多技巧,目前當做黑箱。

可持久化:每次操作盡量用新節點表示而不是修改原節點,這樣就能保留所有歷史信息。 函數式:函數式編程里變量常常是不變的,線段樹的函數式寫法就是這樣。

我們用區間k小值來解釋。

一些預處理

離散化(排序+去重),其實本道題不需要這個操作。 下面的代碼用到了STL的很多技巧,用unique()函數去重,用lower_bound()重新映射a數組。

for (i = 1;i <= n; i++) scanf("%d",&a[i]);for (i = 1;i <= n; i++) b[i] = a[i];sort(b+1,b+n+1);k = unique(b+1,b+n+1) - (b+1);for (i = 1;i <= n; i++) a[i] = lower_bound(b+1,b+k+1,a[i])-b;

假設求整個區間的k小值

這個問題可以用AVL樹做,但是這里介紹一種類似平衡樹的方法。假設某個節點的區間為[l,r],則這個節點記錄的是在a數組中有多少個a[i]滿足l<=a[i]<=r。這樣搜索第k小值時,如果左孩子數量小于k則k小值在左子樹中,反之則在右子樹中。復雜度log(n)。

對于任意區間[L,R]

建立n棵線段樹,每棵維護[1,i]的數字出現情況。 顯然這n棵線段樹每個節點代表的區間都是一樣的,所以這n棵線段樹同構。 用第R棵線段樹去“減”第(L-1)棵線段樹,得出來的結果就是區間[L,R]的情況,對這棵樹套用一遍上面求整個區間的方法就可以求出[L,R]中的k小值。

如何節約空間

上面的方法看起來還是比較具體的,但是會MLE(n棵線段樹)。 下面的優化就是主席樹的精髓:如何扔掉重復的節點。有點抽象,這段話看懂了就比較輕松了。

我們發現,第i棵線段樹和第i+1棵線段樹的區別在于加入了a[i+1]這個數,而a[i+1]在第i棵樹上從根出發向下走,走過的節點+1就變成了第i+1棵線段樹。(你可以自己畫一下看看有什么不同)

也就是說相鄰兩棵線段樹之間不同節點個數至多為log(n)個,換句話說剩下這么多的節點都是一樣的! 那么重復的節點就可以扔掉了。比如說一個節點的左孩子是重復的,那么我不需要多開一個節點,而是直接連到前一棵樹上。 看起來比較復雜,但是編程中有很多技巧,最后代碼比普通線段樹還短。 P.S. 怕以后忘記這里寫的會很詳細。

sol

預處理這里就不再寫了。

建樹

現在連建樹都要重新寫了TAT。 其實只要建一棵空樹即可,后面的樹都是連到這棵樹上。 但是后面再update和query的時候有一個問題:左孩子和右孩子并不能簡單的乘2和乘2加1,如何解決?

//root[i]表示第i棵樹的根的位置void build(int l,int r,int &rt){ rt = ++tot; sum[rt] = 0; if (l == r) return; int m = (l + r) >> 1; build(l,m,ls[rt]); build(m+1,r,rs[rt]);}...tot = 0;build(1,k,root[0]);

用最樸素的方法:一個一個累加! 這里有一個技巧就是用了&,也就是說等到搜到這個點的時候自然會把這個點的位置給傳回來。這個技巧剩下了不少代碼,在后面的update和query中可以自己體會。

更新

//ls表示左孩子位置 rs表示右孩子位置 last表示前一棵樹、當前節點的位置void update(int l,int r,int &rt,int last,int p){ rt = ++tot; ls[rt] = ls[last]; rs[rt] = rs[last];//暫時兩個孩子都連到前一棵樹的對應孩子上 sum[rt] = sum[last] + 1;//這一步可以解釋是哪log(n)個點的值發生了修改! if (l == r) return; int m = (l + r) >> 1; if (p <= m) update(l,m,ls[rt],ls[last],p); else update(m+1,r,rs[rt],rs[last],p);//修改的那個節點開辟出一個新節點 ls/rs會回傳新的節點的位置!前面講到過}...for (i = 1;i <= n; i++) update(1,k,root[i],root[i-1],a[i]);

這樣一來就把這“n棵線段樹”都建好了??梢钥闯鲭m然節點總數為nlog(n),但是卻把所有的情況都記錄下來了,這就是“可持久化”。

查詢

int query(int ss,int tt,int l,int r,int k){ if (l == r) return l; int m = (l + r) >> 1; int cnt = sum[ls[tt]] - sum[ls[ss]];//用第tt棵線段樹減去第ss棵線段樹 if (k <= cnt) return query(ls[ss],ls[tt],l,m,k); else return query(rs[ss],rs[tt],m+1,r,k-cnt);}...while (q--) { scanf("%d%d%d",&ql,&qr,&qk); int res = query(root[ql-1],root[qr],1,k,qk); 有了前面的鋪墊,查詢就比較簡單了。

完整代碼

#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include<ioman
ip>#include<stdlib.h>#include<iostream>#include<algorithm>#define ll long long#define inf 1000000000#define mod 1000000007#define N 100000using namespace std;int a[N],b[N],root[N*20],ls[N*20],rs[N*20],sum[N*20];int n,q,i,tot,k,ql,qr,qk;void build(int l,int r,int &rt){ rt = ++tot; sum[rt] = 0; if (l == r) return; int m = (l + r) >> 1; build(l,m,ls[rt]); build(m+1,r,rs[rt]);}void update(int l,int r,int &rt,int last,int p){ rt = ++tot; ls[rt] = ls[last]; rs[rt] = rs[last]; sum[rt] = sum[last] + 1; if (l == r) return; int m = (l + r) >> 1; if (p <= m) update(l,m,ls[rt],ls[last],p); else update(m+1,r,rs[rt],rs[last],p);}int query(int ss,int tt,int l,int r,int k){ if (l == r) return l; int m = (l + r) >> 1; int cnt = sum[ls[tt]] - sum[ls[ss]]; if (k <= cnt) return query(ls[ss],ls[tt],l,m,k); else return query(rs[ss],rs[tt],m+1,r,k-cnt);}int main(){ cin>>n>>q; for (i = 1;i <= n; i++) scanf("%d",&a[i]); for (i = 1;i <= n; i++) b[i] = a[i]; sort(b+1,b+n+1); k = unique(b+1,b+n+1) - (b+1); for (i = 1;i <= n; i++) a[i] = lower_bound(b+1,b+k+1,a[i])-b; tot = 0; build(1,k,root[0]); for (i = 1;i <= n; i++) update(1,k,root[i],root[i-1],a[i]); while (q--) { scanf("%d%d%d",&ql,&qr,&qk); int res = query(root[ql-1],root[qr],1,k,qk); printf("%d/n",b[res]); } return 0;}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产v综合ⅴ日韩v欧美大片| 性色av一区二区三区免费| 亚洲国产小视频| 黑人巨大精品欧美一区二区一视频| 亚洲第一页中文字幕| 国产热re99久久6国产精品| 亚洲精品一区在线观看香蕉| 精品国产美女在线| 久久91精品国产91久久久| 国产亚洲精品久久| 日韩激情片免费| 国产精品视频在线观看| 黑人巨大精品欧美一区二区三区| 午夜美女久久久久爽久久| 久久天天躁狠狠躁夜夜av| 亚洲精品国产精品乱码不99按摩| 亚洲另类欧美自拍| 欧洲日韩成人av| 欧美日韩国产综合视频在线观看中文| 亚洲欧美日韩在线一区| 中文字幕欧美日韩精品| 亚洲香蕉伊综合在人在线视看| 亚洲第一区在线观看| 亚洲国产成人精品一区二区| 亚洲天堂av综合网| 日韩在线视频二区| 日韩精品在线观看一区| 国产精品第一视频| 亚洲国产精彩中文乱码av在线播放| 搡老女人一区二区三区视频tv| 久久激情视频久久| 91影院在线免费观看视频| 欧美多人乱p欧美4p久久| 国产97在线播放| 国产日韩欧美中文在线播放| 久久久999国产精品| 97精品国产aⅴ7777| 日韩欧美亚洲一二三区| 日韩在线高清视频| 午夜精品久久17c| 欧美日韩中国免费专区在线看| 国产伦精品免费视频| 精品久久香蕉国产线看观看gif| 亚洲精品国产电影| 欧美精品在线视频观看| 国产噜噜噜噜噜久久久久久久久| 欧美精品午夜视频| 欧美国产中文字幕| 久久久www成人免费精品张筱雨| 亚洲成成品网站| 97国产在线视频| 精品一区二区三区四区在线| 成人免费看吃奶视频网站| 秋霞成人午夜鲁丝一区二区三区| 高跟丝袜一区二区三区| 国产aaa精品| 911国产网站尤物在线观看| 伊人伊成久久人综合网小说| 日韩精品极品在线观看| 亚洲欧美综合图区| 亚洲电影成人av99爱色| 欧美性精品220| 亚洲国产欧美日韩精品| 欧美激情网站在线观看| 午夜欧美不卡精品aaaaa| 久久理论片午夜琪琪电影网| 欧美成人激情图片网| 国产亚洲精品成人av久久ww| 色噜噜狠狠色综合网图区| 国产日韩在线视频| 欧美中文在线免费| 亚洲电影免费观看高清完整版| 国产成人精品最新| 久久亚洲国产成人| 亚洲男人的天堂网站| 91产国在线观看动作片喷水| 精品福利在线观看| 91久久在线播放| 色综合天天狠天天透天天伊人| 国产欧美日韩专区发布| 91九色国产社区在线观看| 日韩性生活视频| 国产精品黄色影片导航在线观看| 亚洲三级 欧美三级| 亚洲国产福利在线| 国产丝袜一区视频在线观看| 欧美肥老太性生活视频| 欧美中在线观看| 久久男人av资源网站| 日韩av快播网址| 中文字幕最新精品| 中文字幕在线看视频国产欧美在线看完整| 亚洲精品www久久久久久广东| 久久久久久久999| 亚洲在线免费观看| 98视频在线噜噜噜国产| 最近2019免费中文字幕视频三| 日韩精品黄色网| 欧美日韩不卡合集视频| 在线播放国产一区中文字幕剧情欧美| 色妞在线综合亚洲欧美| 欧美大成色www永久网站婷| 国产狼人综合免费视频| 日韩精品有码在线观看| 国产91免费观看| 午夜免费在线观看精品视频| 91亚洲国产成人久久精品网站| 精品久久香蕉国产线看观看亚洲| 久久中文字幕在线| 国产精品第七影院| 国产精品99久久99久久久二8| 亚洲另类图片色| 亚洲一区二区在线播放| 亚洲va欧美va在线观看| 欧美在线视频观看免费网站| 日韩在线播放一区| 日韩免费不卡av| 欧美亚洲另类视频| 欧美性高潮在线| 日韩激情视频在线播放| 91在线免费视频| 国产成人激情小视频| 国产日韩欧美在线视频观看| 国产精品高清免费在线观看| 国产精品视频久久久| 人九九综合九九宗合| 国产精品爽黄69| 91超碰caoporn97人人| 午夜精品理论片| 欧美性猛交xxxx免费看| 九色精品免费永久在线| 欧美午夜丰满在线18影院| 91欧美视频网站| 欧美一区在线直播| 国产不卡一区二区在线播放| 黄色成人av网| 久热在线中文字幕色999舞| 日韩精品在线电影| 亚洲视频在线看| 欧美性生交大片免网| 日韩经典中文字幕在线观看| 亚洲经典中文字幕| 欧美精品激情在线观看| 欧美一级淫片aaaaaaa视频| 美女视频久久黄| 中日韩午夜理伦电影免费| 亚洲天堂网在线观看| 日韩电影中文字幕在线观看| 欧美激情第三页| 亚洲欧美日韩直播| 久久精品视频在线观看| 亚洲永久免费观看| 91免费人成网站在线观看18| 91影院在线免费观看视频| 成人黄色影片在线| 一区二区在线视频播放| 欧美一级大片在线免费观看| 一区二区在线免费视频| 一本色道久久综合亚洲精品小说| 亚洲精品福利资源站| 日韩综合视频在线观看| 国产日韩欧美日韩| 国产免费一区二区三区在线能观看| 夜夜嗨av色综合久久久综合网|