《洛谷P3834》

回顾一下可持久化线段树。

这题是经典的查询静态区间第k小。

对于主席树,可以将每个区间位置,看成第i个历史版本,然后对每个点去维护一棵树。

然后对于第i个点维护的x位置,存的值是1~i的x的前缀和。

查询的时候,比较下前缀和左边是否满足即可。

注意换到右边时,需要减去左区间个数,保证相对第k小。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<string,int> pii;
const int N = 2e5+5;
const int M = 1e5+5;
const LL Mod = 199999;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;
void FRE(){/*freopen("data1.in","r",stdin);
freopen("data1.out","w",stdout);*/}

int n,m,rt[N*20],top = 0;
LL a[N],b[N],mp[N];
struct Node{int L,r;LL sum;}node[N*20];
int build(int L,int r)
{
    int idx = ++top;
    node[idx].sum = 0;
    if(L == r) return idx;
    int mid = (L+r)>>1;
    node[idx].L = build(L,mid);
    node[idx].r = build(mid+1,r);
    return idx;
}
void Pushup(int idx)
{
    node[idx].sum = node[node[idx].L].sum + node[node[idx].r].sum;
}
int update(int x,int L,int r,int pos)
{
    int idx = ++top;
    node[idx] = node[x];
    if(L == r){node[idx].sum++;return idx;}
    int mid = (L+r)>>1;
    if(mid >= pos) node[idx].L = update(node[x].L,L,mid,pos);
    else node[idx].r = update(node[x].r,mid+1,r,pos);
    Pushup(idx);
    return idx;
}
int query(int lidx,int ridx,int L,int r,int k)
{
    if(L == r) return L;
    int mid = (L+r)>>1;
    int Lsum = node[node[ridx].L].sum-node[node[lidx].L].sum;
    if(Lsum >= k) return query(node[lidx].L,node[ridx].L,L,mid,k);
    else return query(node[lidx].r,node[ridx].r,mid+1,r,k-Lsum);
}
int main()
{
    n = read(),m = read();
    for(rg int i = 1;i <= n;++i) a[i] = read(),b[i] = a[i];
    sort(a+1,a+n+1);
    int len = unique(a+1,a+n+1)-a-1;
    for(rg int i = 1;i <= n;++i) 
    {
        int pos = lower_bound(a+1,a+len+1,b[i])-a;
        mp[pos] = b[i];
        b[i] = pos;
    }
    rt[0] = build(1,len);
    for(rg int i = 1;i <= n;++i) rt[i] = update(rt[i-1],1,len,b[i]);
    while(m--)
    {
        int L,r,k;
        L = read(),r = read(),k = read();
        int ans = query(rt[L-1],rt[r],1,len,k);
        printf("%d\n",mp[ans]);
    }
    system("pause");
}
View Code

 

posted @ 2020-09-05 13:55  levill  阅读(153)  评论(0编辑  收藏  举报