第k大的數(主席樹模板)

2022-05-01 18:51:08 字數 2236 閱讀 2846

描述

你為macrohard公司的資料結構部門工作,你的工作是重新寫乙個資料結構,這個資料結構能快速地找到一段數列中第k大的數。

就是說,給定乙個整數數列a[1..n],其中每個元素都不相同,你的程式要能回答一組格式為q (i , j , k)的查詢,q(i, j ,k)的意思是「在a[i..j]中第k大的數是多少?」

例如令 a = ,查詢格式為q (2 , 5 , 3),數列段a[2..5] = ,第3大的數是5,所以答案是5。

輸入檔案第一行包括乙個正整數n,代表數列的總長度,還有乙個數m,代表有m個查詢。 n,m滿足:1≤n≤100 000, 1≤m≤5 000 第二行有n個數,代表數列的元素,所有數都不相同,而且不會超過109 接下來有m行,每行三個整數i , j , k,代表一次查詢, i , j , k滿足1≤i≤j≤n, 1≤k≤j − i + 1

輸出輸出每個查詢的答案,用換行符隔開

樣例輸入[複製]

7 31 5 2 6 3 7 4

2 5 3

4 4 1

1 7 3

樣例輸出[複製]56

3

1

/*template of chair tree

2lower_bound函式是用來返回乙個值在單調遞增數列裡大於等於這個值的最小值

3upper_bound函式實際上就是將lower_bound裡面的大於等於改成了嚴格大於

4這裡p的作用僅僅是在記錄這個點的編號,我們用一維陣列來儲存樹,只是該指向哪個位置

5同時我們輸入了幾個數就維護那麼大的區間,不一定一定要從1列舉到最大值,比如說1,8,5,4

6僅需要四個陣列位置,我每往後加乙個數字就要建一棵節約空間的線段樹,類似於ac自動機的思想

7那麼這個陣列對應的a陣列就是 1,4,3,2,每加乙個就相當於乙個節點修改了值然後向上維護,不過這

8裡沒有使用pushup函式,而是直接在二分的過程中進行累加,可以更好地維護值

9為什麼我們要維護這麼多棵線段樹,因為我們要像字首和陣列一樣通過乙個版本減去前面的版本

10來獲得所需區間的排序資訊,再進行二分就可以了.

1112

*/13 #include14

#define n 100005

15using

namespace

std;

16struct

nodet[n*40

];19

int a[n],b[n],n,m,rt[n*40

];20

int tot=0

;21 inline void build(int &p,int l,int r)

29 inline void update(int &p,int l,int r,int o,int

k)41 inline int query(int p1,int p2,int l,int r,int

k)48 inline long

long

read()

55while

(isdigit(ch))

59return ans*w;60}

61 inline void write(long

long

x)66

if(x>9)write(x/10

);67 putchar(x%10+'0'

);68}69

intmain()

76 sort(b+1,b+n+1);//

lower_bound函式必須是嚴格單調遞增,配合unique函式

77int siz=unique(b+1,b+n+1)-b-1;//

進行去重操作

78 build(rt[0],1,siz);//

對第0棵樹進行建圖

79for(int i=1;i<=n;++i)a[i]=lower_bound(b+1,b+siz+1,a[i])-b;

80/*

找到a[i]該在的位置,此時a陣列的作

81用變為了記錄對應數字應該在的下標 ,

82類似於一般我們是陣列下標對應值,而

83這裡新加的操作就是原數列的每個值

84應該對應到排序過後的第幾個位置,

85相當於第幾名

86*/

87for(int i=1;i<=n;++i)update(rt[i],1,siz,rt[i-1

],a[i]);

88while(m--)

93return0;

94 }

區間第k大的數 主席樹

套主席樹求區間第k小的數的模板,然後求區間 l,r 第k大的數就等於求區間 l,r 第r l 1 k小的數 下標從1開始 區間第k小值問題 有n個數,多次詢問乙個區間 l,r 中第k小的值是多少。查詢區間 l,r 中的第k小值 我們按照從1到n的順序依次將資料插入可持久化的線段樹中,將會得到n 1個...

區間第k大(主席樹)

學了一下主席樹模板題,當初看了網上的主席樹講解都沒有看懂,後面看了嗶哩嗶哩的uestc的主席樹,終於看懂了思想。每次更新的複雜度都為logn。每次更新的話就是對要更新的點路徑上的點重新更加乙個,然後進行對沒有影響的那些進行連邊。然後用乙個root記錄每乙個線段樹的根節點下標。include incl...

主席樹區間第K大

主席樹的實質其實還是一顆線段樹,然後每一次修改都通過上一次的線段樹,來新增新邊,使得每次改變就改變logn個節點,很多節點重複利用,達到節省空間的目的。1.不帶修改的區間第k大。hdu 2665 模板題 1 include2 using namespace std 3 define fopen fr...