主席树笔记

就没啥好记录的。。。。

主席树思想很简单 , 难在于应用。。。。。

这个玩意是用来维护可以通过 加减法得到单独一个区间的。。(要是复杂度接受,怎么搞都可以)

就没有了

比较容易写。。。。(我不看板子都可以自己写出来。。。常数比较大,,)

#include<bits/stdc++.h>
#define MAXN 200005
typedef long long ll;
using namespace std;

ll n,q,a[MAXN],b[MAXN],tot = 0,rt[MAXN];

struct node{
	ll sum,lc,rc;
}t[MAXN * 50];

int build(int op , int l , int r){
	int zz = ++tot;
	if(l == r)return zz;
	int mid = (l + r) >> 1;
	t[zz].lc = build(t[op].lc , l , mid);
	t[zz].rc = build(t[op].rc , mid + 1 , r);
	t[zz].sum = t[t[zz].lc].sum + t[t[zz].rc].sum;
	return zz;
}

int update(int op , int l , int r , int dx){
	int zz = ++tot;
	t[zz].lc = t[op].lc;
	t[zz].rc = t[op].rc;
	if(l == r){
		t[zz].sum += t[op].sum + 1;
		return zz;
	}
	int mid = (l + r) >> 1;
	if(dx <= mid)t[zz].lc = update(t[op].lc , l , mid , dx);
	else t[zz].rc = update(t[op].rc , mid + 1 , r , dx);
	t[zz].sum = t[t[zz].lc].sum + t[t[zz].rc].sum;
	return zz;
}

int que(int l , int r , int op1 , int op2 , int dx){
	if(l >= r)return l;
	int zz = t[t[op2].lc].sum - t[t[op1].lc].sum;
	int mid = (l + r) >> 1;
	if(zz >= dx)return que(l , mid , t[op1].lc , t[op2].lc , dx);
	return que(mid + 1 , r , t[op1].rc , t[op2].rc , dx - zz);
}


int main(){
	cin>>n>>q;
	for(int i = 1 ; i <= n ; i++){
		scanf("%lld" , &a[i]);
		b[i] = a[i];
	}
	sort(b + 1 , b + 1 + n);
	int js = 0;
	js = unique(b + 1 , b + 1 + n) - b - 1;
	rt[0] = build(0 , 1 , js);
	for(int i = 1 ; i <= n ; i++){
		int t = lower_bound(b + 1 , b + 1 + js , a[i]) - b;
		rt[i] = update(rt[i - 1] , 1 , js , t);
	}
	for(int i = 1 ; i <= q ; i++){
		int x,y,z;
		scanf("%d%d%d" , &x , &y , &z);
		cout<<b[que(1 , js , rt[x - 1] , rt[y] , z)]<<endl;	
	}
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值