就没啥好记录的。。。。
主席树思想很简单 , 难在于应用。。。。。
这个玩意是用来维护可以通过 加减法得到单独一个区间的。。(要是复杂度接受,怎么搞都可以)
就没有了
比较容易写。。。。(我不看板子都可以自己写出来。。。常数比较大,,)
#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;
}
}
2323

被折叠的 条评论
为什么被折叠?



