zoukankan      html  css  js  c++  java
  • 【模板】可持久化线段树 1(主席树)

    题目背景

    这是个非常经典的主席树入门题——静态区间第K小

    数据已经过加强,请使用主席树。同时请注意常数优化

    题目描述

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

    输入格式

    第一行包含两个正整数N、M,分别表示序列的长度和查询的个数。

    第二行包含N个整数,表示这个序列各项的数字。

    接下来M行每行包含三个整数l, r, kl,r,k , 表示查询区间[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

    样例数据说明:

    N=5,数列长度为5,数列从第一项开始依次为[25957, 6405, 15770, 26287, 26465 ]

    第一次查询为[2, 2]区间内的第一小值,即为6405

    第二次查询为[3, 4]区间内的第一小值,即为15770

    第三次查询为[4, 5]区间内的第一小值,即为26287

    第四次查询为[1, 2]区间内的第二小值,即为25957

    第五次查询为[4, 4]区间内的第一小值,即为26287

    分析:

    模板题???去TM的。。。一道模板题调我一晚上。。。(除了treap,树剖外调的时间最长一道题目)

    PS:目前调(不含第一遍写的时间)的时间最久的(不看题解):

    1.猪国杀??? 1个月 (还没写好。。。)

    2.treap 4个小时

    2.树剖 4个小时

    4.主席树 3个小时

    4.有机化学之神之偶尔会作弊 3个小时(神题。。。结合多种算法。。)

    6.网络流 2.5个小时

    7.字符串的展开 2个小时

    7.牛绣花(你TM试试自己推这题的公式。。。) 2个小时

    9.洛谷P1962 斐波那契数列(哼哼,你自己看看数据范围) 1.5小时

    9.[AHOI2009]中国象棋(你试试这题递推方程。。。) 1.5小时

    CODE:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 const int M=30000005;
     6 int p[M],a[M];
     7 int n,m;
     8 int rt[M],tot;
     9 struct tree{
    10     int son[2],size;
    11 }node[M];
    12 void build (int &rt,int l,int r){
    13     rt=++tot;
    14     int mid=(l+r)>>1;
    15     if (!(l^r)) return ;
    16     build (node[rt].son[0],l,mid);
    17     build (node[rt].son[1],mid+1,r);
    18 }
    19 int bsearch(int k){
    20     int l=1,r=m;
    21     while (l<=r){
    22         int mid=(l+r)>>1;
    23         if (p[mid]==k) return mid;
    24         if (p[mid]<k) l=mid+1;
    25         else r=mid-1;
    26     }
    27     return l;
    28 }
    29 void np(int &rt,int lst,int l,int r,int val){
    30     node[rt=++tot]=node[lst];
    31     ++node[rt].size;
    32     int mid=(l+r)>>1;
    33     if (!(l^r)) return ;
    34     if (val<=mid) np(node[rt].son[0],node[lst].son[0],l,mid,val);
    35     else np(node[rt].son[1],node[lst].son[1],mid+1,r,val);
    36 }
    37 int query(int rt1,int rt2,int l,int r,int k){
    38     int mid=(l+r)>>1;
    39     if (!(l^r)) return p[l];
    40     if(node[node[rt2].son[0]].size-node[node[rt1].son[0]].size>=k) 
    41         return  query(node[rt1].son[0],node[rt2].son[0],l,mid,k); 
    42     else
    43         return  query(node[rt1].son[1], node[rt2].son[1],mid+1,r,k-node[node[rt2].son[0]].size+node[node[rt1].son[0]].size); 
    44 }
    45 int read(){
    46     int res=0;
    47     int f=1;
    48     char c=getchar();
    49     while (c>'9'||c<'0') {
    50         if (c=='-') f=-1;
    51         c=getchar();
    52     }
    53     while (c<='9'&&c>='0') {
    54         res=(res<<3)+(res<<1)+c-'0';
    55         c=getchar();
    56     }
    57     return res*f;
    58 }
    59 int main(){
    60     scanf ("%d",&n);
    61     int mm;
    62     scanf ("%d",&mm);
    63     for (int i=1;i<=n;i++)
    64         a[i]=read(),p[i]=a[i];
    65     sort(p+1,p+n+1);
    66     m=unique(p+1,p+n+1)-p-1;
    67     build(rt[0],1,m);
    68     //cout<<m<<endl;
    69     /*for (int i=1;i<=m;i++)
    70         cout<<p[i]<<endl;*/
    71     for (int i=1;i<=n;i++){
    72         //cout<<a[i]<<" "<<bsearch(a[i])<<endl;
    73         np(rt[i],rt[i-1],1,m,bsearch(a[i]));
    74     }
    75     while (mm--){
    76         int i,j,l;
    77         i=read(),j=read(),l=read();
    78         printf("%d
    ",query(rt[i-1],rt[j],1,m,l));
    79     }
    80     //system("pause");
    81     return 0;
    82 }

     

  • 相关阅读:
    Docker的安装、配置及其基本使用
    Java提升七:注解
    Java提升六:泛型
    Java提升五:反射与动态代理
    MySQL中如何将主键默认值设为UUID()
    图解Mybatis框架原理及使用
    Java提升四:Stream流
    Java提升三:函数式接口
    Java提升二:Lambda表达式与方法引用
    java提升一:内部类
  • 原文地址:https://www.cnblogs.com/kanchuang/p/11259956.html
Copyright © 2011-2022 走看看