• 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)]);
          }
    }
    
    
  • 相关阅读:
    SQL UNION 和 UNION ALL 操作符
    JavaScript--验证码随机生成
    C#基础 out和ref
    远程连接身份验证错误,又找不到加密Oracle修正
    ASP.Net WebAPI -- 简单实现增删改查
    SpringBoot发送邮箱验证码
    VMware虚拟机安装Linux系统详细教程
    SpringBoot实现登陆拦截
    JavaScript 实例、构造函数、原型对象关系图
    JavaScript创建对象的几种方式总结
  • 原文地址:https://www.cnblogs.com/mmmqqdd/p/10848731.html
Copyright © 2020-2023  润新知