數據結構入門2—主席樹

聽說劃分樹能解決的問題主席樹基本都能解決,感覺主席樹好理解又好寫(至少比那些亂七八糟的平衡樹親切多了),乾脆就不學劃分樹了qaq

%%%lljakfather所有題都是主席樹模板題

其實就是可持久化線段樹啦。

假如一個序列有n個數,有m次修改。

首先我們想一想最暴力的方法就是建m顆線段樹,雖然想想就心累,空間很難開的下。

然後發現有些節點其實是可以多次利用的,於是把兒子指針遷過去就行啦(然而我不會指針)

主席樹模板題—求區間第k小

表示不會利用STL

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
int n,m;
int root[maxn],arr[maxn],b[maxn],tot=0,sz;

int aa,ff;char cc;
int read() {
	aa=0;ff=1;cc=getchar();
	while((cc<'0'|cc>'9')&&cc!='-') cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	return aa*ff;
}

struct Node{
	int l,r,lson,rson,sum;
}node[20*maxn];

void bld(int pos,int last,int l,int r,int x) {
	node[pos].l=l;node[pos].r=r;
	node[pos].sum=node[last].sum+1;
	if(l==r) return;
	int mid=(l+r)>>1;
	if(x<=b[mid]) {
		node[pos].rson=node[last].rson;
		bld(node[pos].lson=++tot,node[last].lson,l,mid,x);
	}
	else {
		node[pos].lson=node[last].lson;
		bld(node[pos].rson=++tot,node[last].rson,mid+1,r,x);
	}
}

int q(int pos1,int pos2,int k) {
	if(node[pos2].l==node[pos2].r) return node[pos2].l;
	if(k<=node[node[pos2].lson].sum-node[node[pos1].lson].sum) return q(node[pos1].lson,node[pos2].lson,k);
	k-=node[node[pos2].lson].sum-node[node[pos1].lson].sum;
	return q(node[pos1].rson,node[pos2].rson,k);
}

int main() {
	n=read();m=read();
	for(int i=1;i<=n;++i) arr[i]=b[i]=read();
	sort(b+1,b+n+1);sz=n;
	root[0]=++tot;
	for(int i=1;i<=n;++i) {
		root[i]=++tot;
		bld(tot,root[i-1],1,sz,arr[i]);
	}
	int x,y,z;
	for(int i=1;i<=m;++i) {
		x=read();y=read();z=read();
		printf("%d\n",b[q(root[x-1],root[y],z)]);
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章