具體哪道題目就不說了,區間第k大可以說是很常見的題目。寫了一上午線段樹終於是記起了一點以前學過的東西。
這裡說的是沒有修改的區間查詢。對於線段樹的結構體,一開始搜了一下,說是要按照歸併排序的方法去建樹,所以說每個節點要記錄陣列咯??這樣的話每個節點還要記乙個陣列,太麻煩,空間占用也變大了。所以有另一種方法,直接用乙個陣列,在節點中記錄該節點對應的該陣列中的範圍,這樣就可以節省空間。
建好樹之後就是查詢,這裡要到兩個查詢,第乙個是查詢給定值在給定範圍內的下標,第二個查詢是第乙個查詢中要呼叫的,用來尋找在具體的某乙個節點中它的下標。最後在主程式中二分答案,找到其在給定範圍的下標,判斷即可。
#include#include#define maxn 10100
#define inf 1111111111
struct s;
s tr[maxn*4];
int d[maxn*20],cnt;
int a[maxn];
void build(int rt,int lr,int rr)
int mid=(tr[rt].l+tr[rt].r)>>1;
build(rt*2,lr,mid);
build(rt*2+1,mid+1,rr);
tr[rt].ll=cnt+1;
// printf("cnt==%d\n",cnt);
int l1=tr[rt*2].ll,r1=tr[rt*2].rr;
int l2=tr[rt*2+1].ll,r2=tr[rt*2+1].rr;
while(l1<=r1&&l2<=r2)
return ls-ll;
}int query1(int rt,int ls,int rs,int ans)
int mid=(tr[rt].l+tr[rt].r)>>1;
int hh=0;
if(ls<=mid) hh+=query1(rt*2,ls,rs,ans);
if(rs>=mid+1) hh+=query1(rt*2+1,ls,rs,ans);
return hh;
}int main(){
int n,x,y,k;
cnt=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
int m;
scanf("%d",&m);
while(m--){
scanf("%d%d%d",&x,&y,&k);
k=y-x-k+2;
// printf("k==%d\n",k);
int lll=-inf,rrr=inf,mid;
while(lll>1;
int tmp=query1(1,x,y,mid);
// printf("lll===%d rrr====%d mid==%d tmp==%d\n",lll,rrr,mid,tmp);
if(tmp
加油,馬上藍橋杯。
區間第k大(主席樹)
學了一下主席樹模板題,當初看了網上的主席樹講解都沒有看懂,後面看了嗶哩嗶哩的uestc的主席樹,終於看懂了思想。每次更新的複雜度都為logn。每次更新的話就是對要更新的點路徑上的點重新更加乙個,然後進行對沒有影響的那些進行連邊。然後用乙個root記錄每乙個線段樹的根節點下標。include incl...
主席樹區間第K大
主席樹的實質其實還是一顆線段樹,然後每一次修改都通過上一次的線段樹,來新增新邊,使得每次改變就改變logn個節點,很多節點重複利用,達到節省空間的目的。1.不帶修改的區間第k大。hdu 2665 模板題 1 include2 using namespace std 3 define fopen fr...
可持久化線段樹求區間第k大
老爺口諭,有n個數 10 9 n 10 9,每個數的範圍在 0,10 5 給定m個詢問,每次詢問區間 l,r 的第k小值 可持久化線段樹,舔的老爺的模板 1 include2 include3 using namespace std 4 define maxn 100005 5int val max...