這個題目的意思是給你乙個區間,讓你找到在某個給出的子區間當中第k大的數。
這是我的第乙個劃分樹題目,因為之前做了好多線段樹的題目了,看了看書上基本的**,然後按照自己的思路寫了出來。
按照這個題目的思路,得用到二分,把給出的元素x[n]排好序y[n],對於乙個給出的子區間,那麼第k大的元素應該滿足兩點:
(1)在區間當中至少存在k個不超過第k大的元素
(2)在區間當中小於第k大的元素不到k個
從排好序列的區間當中取出mid,劃分樹當中每個節點儲存的是乙個區間內排好序的元素,當這個節點所在的區間完全包含在被給出的區間的時候,就找出小於等於y[mid]的元素的個數,每次查詢完成以後得出小於等於y[mid]的元素的個數t,如果t>=k,就讓right=mid,否則的話就讓left=mid;這樣二分可以很快找到滿足條件的y[mid],最後輸出的y[mid]就是查詢到的區間當中的第k大的數
#include #include #include #include #define tag 1200
#define maxn 100010
using namespace std;
int x[maxn];
int y[maxn];
vectorve[4*maxn];
void build(int now,int l,int r)
int mid=(l+r)>>1;
build(2*now,l,mid);
build(2*now+1,mid+1,r);
ve[now].resize(r-l+1);//目的是申請足夠容納[l,r]內元素的記憶體單元
merge(ve[2*now].begin(),ve[2*now].end(),ve[2*now+1].begin(),ve[2*now+1].end(),ve[now].begin());//由下往上區間合併,合併的同時完成了排序
}int query(int now,int l,int r,int tl,int tr,int val)//查詢操作,關鍵地方
else
}int main()
; while(cin>>n>>m)
sort(y+1,y+1+n);
build(1,1,n);
int l,r,val,mid;
int sum;
while(m--)
else
}printf("%d\n",y[right]);}}
return 0;
}
劃分樹學習 poj 2104
開始學習劃分樹 按照網上的題目大概敲了下 還有些不懂的地方 尤其是查詢 還不是很懂 下次在看懂 下面是這題的 include include includeusing namespace std int const tcnt 100100 struct node tree tcnt 4 int a ...
主席樹模板 POJ2104
離散化 對陣列排完序後用unique去重,unique返回的是去重後的陣列的末位址,減去第乙個元素的位址就能得到去重後的陣列大小,用lower bound查詢原數字在排序去重後的序列中的位序,用位序代替數字完成離散化。include include using namespace std defin...
主席樹模板(poj2104)
主席樹是可持久化線段樹,可以記錄線段樹的歷史版本。中和線段樹不同的是,l,r記錄的是左右子樹編號,因為普通的線段樹版本中,左右子樹自然就是o 1和o 1 1,但是主席樹中並不保證這個特性,所以需要記錄一下。是 include include include include include using...