码迷,mamicode.com
首页 > 其他好文 > 详细

[可持久化权值线段树] [模板] [指针版本]

时间:2021-03-06 14:43:50      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:printf   ret   space   print   pool   std   bit   turn   线段树   

[可持久化权值线段树] [模板] [指针版本]

\[1 \leq n \leq 2e5\|a_i| \leq 1e9 \]

感觉动态开点用指针好理解一点

代码

#include<bits/stdc++.h>
#define eps 1e-8
#define equals(a,b) (fabs(a - b) < eps)
#define getsize(p) (p?p -> siz : 0)
using namespace std;

typedef long long ll;

const ll MOD = 1e9 + 7;
const int maxn = 2e5 + 5;

ll rd(){
	ll x = 0;
	int f = 1;
	char ch = getchar();
	while(ch < ‘0‘ || ch > ‘9‘) {
		if(ch == -1) f = -1;
		ch = getchar();
	}
	while(ch >= ‘0‘ && ch <= ‘9‘) {
		x = x * 10 + ch - ‘0‘;
		ch = getchar();
	} 
	return  x * f;
}


struct SegmentTree{
	int n;
	vector<int> sum,tag;
	SegmentTree(){}
	SegmentTree(int n):n(n),sum(((n + 1) << 2)),tag(((n + 1) << 2)) {}
	int push_up(int i){
		sum[i] = sum[i << 1] + sum[i << 1|1];
	}
	void update(int i,int l,int r,int v){
		sum[i] += (r - l + 1) * v;
		tag[i] += v;
	}
	void push(int i,int l,int r){
		int mid = l + r >> 1;
		if(tag[i]) {
			update(i << 1,l,mid,tag[i]);
			update(i << 1|1,mid + 1,r,tag[i]);
			tag[i] = 0;
		}
	}
	void update(int i,int l,int r,int L,int R,int v){
		if(l > R || r < L) return;
		if(l >= L && r <= R) return update(i,l,r,v);
		int mid = l + r >> 1;
		push(i,l,r);
		update(i << 1,l,mid,L,R,v);
		update(i << 1|1,mid + 1,r,L,R,v);
		push_up(i);
	} 
	int query(int i,int l,int r,int L,int R){
		if(l > R || r < L) return 0;
		if(l >= L && r <= R) return sum[i];
		int mid = l + r >> 1;
		push(i,l,r);
		return query(i << 1,l,mid,L,R) + query(i << 1|1,mid + 1,r,L,R); 
	}
};

struct ZXS{
	struct Node{
		int l,r,siz;
		Node* ls,*rs;
	}pool[40 * maxn];
	int top;
	Node* rt[maxn];
	Node* copyNode(Node* rt){
		Node* p = pool + (++top);
		pool[top] = *rt;
		return p;
	}
	Node* newNode(int l,int r){
		Node* p = pool + (++top);
		p -> l = l,p -> r = r;
		return p;
	}
	Node* insert(Node* rt,int l,int r,int x){
		Node* p;
		if(rt) p = copyNode(rt);
		else p = newNode(l,r);
		p -> siz++;
		if(p -> l == x && p -> r == x) return p;
		int mid = l + r >> 1;
		if(x <= mid) p -> ls = insert(p -> ls,l,mid,x);
		else p -> rs = insert(p -> rs,mid + 1,r,x);
		return p;
	}
	int query(Node* pL,Node* pR,int k){
		if(pR -> l == pR -> r) return pR -> l;
		int n;
		if(!pL) {
			n = getsize(pR -> ls);
			if(n >= k) return query(0,pR -> ls,k);
			else return query(0,pR -> rs,k - n);
		} 
		else{
			n = getsize(pR -> ls) - getsize(pL -> ls);
			if(n >= k) return query(pL -> ls,pR -> ls,k);
			else return query(pL -> rs,pR -> rs,k - n);
		}
	}
}seg;

int main(){
	int n = rd();
	int q = rd();
	vector<int> v(n),vv(n);
	for(int i = 0;i < n;i++)
		v[i] = vv[i] = rd();
	sort(v.begin(),v.end());
	for(int i = 0;i < n;i++){
		int x = lower_bound(v.begin(),v.end(),vv[i]) - v.begin();
		seg.rt[i + 1] = seg.insert(seg.rt[i],1,n,x + 1);	
	}
	while(q--){
		int l = rd();
		int r = rd();
		int k = rd();
		printf("%d\n",v[seg.query(seg.rt[l - 1],seg.rt[r],k) - 1]);
	}
}
	

[可持久化权值线段树] [模板] [指针版本]

标签:printf   ret   space   print   pool   std   bit   turn   线段树   

原文地址:https://www.cnblogs.com/hznumqf/p/14488674.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!