P3834 【模板】可持久化线段树 1(主席树)

P3834 【模板】可持久化线段树 1(主席树)

题目描述

如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值。

输入格式:

第一行包含两个正整数N、M,分别表示序列的长度和查询的个数。
第二行包含N个整数,表示这个序列各项的数字。
接下来M行每行包含三个整数l,r,k l, r, kl,r,k , 表示查询区间[l,r][l, r][l,r]内的第k小值。

输出格式:

输出包含k行,每行1个整数,依次表示每一次查询的结果

输入输出样例

输入样例#1:
5 5
25957 6405 15770 26287 26465
2 2 1
3 4 1
4 5 1
1 2 2
4 4 1

输出样例#1:
6405
15770
26287
25957
26287

数据范围:

(1 leq N, M leq 2cdot 10^5)

对于数列中的所有数(a_i),均满足(-{10}^9 leq a_i leq {10}^9)

题解:

复习模板题,顺便写个博客吧,封装成立一个类。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 200050
int n,m,a[N],kth[N],rt[N];
template<typename T>void read(T&x)
{
  ll k=0; char c=getchar();
  x=0;
  while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
  if (c==EOF)exit(0);
  while(isdigit(c))x=x*10+c-'0',c=getchar();
  x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
struct PrimeTree
{
    struct Tree{int l,r,ls,rs,sum;}tr[N*22];
    int num;
    void bt(int &x,int l,int r)
        {
            x=++num;
            tr[x].l=l; tr[x].r=r; tr[x].sum=0;
            if (l==r)return;
            int mid=(l+r)>>1;
            bt(tr[x].ls,l,mid);
            bt(tr[x].rs,mid+1,r);
        }
    void add(int &x,int last,int p)
        {
            x=++num;
            tr[x]=tr[last];
            tr[x].sum++;
            if (tr[x].l==tr[x].r)return;
            int mid=(tr[x].l+tr[x].r)>>1;
            if (p<=mid)add(tr[x].ls,tr[last].ls,p);
            else add(tr[x].rs,tr[last].rs,p);
        }
    int ask(int x,int y,int k)
        {
            if (tr[x].l==tr[x].r)return tr[x].l;
            int lsum=tr[tr[y].ls].sum-tr[tr[x].ls].sum;
            if (lsum>=k)return ask(tr[x].ls,tr[y].ls,k);
            else return ask(tr[x].rs,tr[y].rs,k-lsum);
        }
    void init()
        {
            num=0;
            bt(rt[0],1,n);
            for(int i=1;i<=n;i++)add(rt[i],rt[i-1],a[i]);
        }
}A;
int main()
{
#ifndef ONLINE_JUDGE
  freopen("aa.in","r",stdin);
#endif
  read(n); read(m);
  for(int i=1;i<=n;i++)read(a[i]),kth[i]=a[i];
  sort(kth+1,kth+n+1);
  int num=unique(kth+1,kth+n+1)-kth-1;
  for(int i=1;i<=n;i++)a[i]=lower_bound(kth+1,kth+num+1,a[i])-kth;
  A.init();
  for(int i=1;i<=m;i++)
      {
          int x,y,k;
          read(x); read(y); read(k);
          printf("%d
",kth[A.ask(rt[x-1],rt[y],k)]);
      }
}

原文地址:https://www.cnblogs.com/mmmqqdd/p/10848731.html