zoukankan      html  css  js  c++  java
  • HDU 2665.Kth number-可持久化线段树(无修改区间第K小)模板 (POJ 2104.K-th Number 、洛谷 P3834 【模板】可持久化线段树 1(主席树)只是输入格式不一样,其他几乎都一样的)

    Kth number

    Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 16941    Accepted Submission(s): 5190


    Problem Description
    Give you a sequence and ask you the kth big number of a inteval.
     
    Input
    The first line is the number of the test cases. 
    For each test case, the first line contain two integer n and m (n, m <= 100000), indicates the number of integers in the sequence and the number of the quaere. 
    The second line contains n integers, describe the sequence. 
    Each of following m lines contains three integers s, t, k. 
    [s, t] indicates the interval and k indicates the kth big number in interval [s, t]
     
    Output
    For each test case, output m lines. Each line contains the kth big number.
     
    Sample Input
    1
    10 1
    1 4 2 3 5 6 7 8 9 0
    1 3 2
     
    Sample Output
    2
     
    Source
     
     
     
     
     
    题意就是查询区间第K小,可持久化线段树就可以上场了。
     
    没学可持久化数据结构之前,感觉这个东西是个很高大上,很厉害的东西,等到了解之后发现,就是因为问题的产生所以在原有线段树的基础上有所更新,支持查询历史版本。
    如果每更新一次就新建一整棵线段树简直是丧心病狂,所以直接新开节点保存更新的那一条链就可以。
    这种东西还是需要自己慢慢体会的,加油,咸鱼。
     
    代码:
      1 //无修改区间第K小-可持久化线段树(权值线段树+可持久化)
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<bitset>
      7 #include<cassert>
      8 #include<cctype>
      9 #include<cmath>
     10 #include<cstdlib>
     11 #include<ctime>
     12 #include<deque>
     13 #include<iomanip>
     14 #include<list>
     15 #include<map>
     16 #include<queue>
     17 #include<set>
     18 #include<stack>
     19 #include<vector>
     20 using namespace std;
     21 typedef long long ll;
     22 typedef pair<int,int> pii;
     23 
     24 const double PI=acos(-1.0);
     25 const double eps=1e-6;
     26 const ll mod=1e9+7;
     27 const int inf=0x3f3f3f3f;
     28 const int maxn=1e5+10;
     29 const int maxm=100+10;
     30 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
     31 #define lson l,m
     32 #define rson m+1,r
     33 
     34 int a[maxn],b[maxn],sum[maxn<<5],L[maxn<<5],R[maxn<<5];//sum线段树里保存的值,L左儿子,R右儿子
     35 int n,m,sz=0;
     36 
     37 void build(int &rt,int l,int r)//建棵空树
     38 {
     39     rt=++sz;sum[rt]=0;//动态开点,初始值为0,空树
     40     if(l==r){
     41         return ;
     42     }
     43 
     44     int m=(l+r)>>1;
     45     build(L[rt],lson);
     46     build(R[rt],rson);
     47 }
     48 
     49 void update(int pr,int &rt,int l,int r,int x)
     50 {
     51     rt=++sz;sum[rt]=sum[pr]+1;//插入序列,首先继承以前的线段树 然后直接单点+1就可以
     52     L[rt]=L[pr];R[rt]=R[pr];
     53     if(l==r){
     54         return ;
     55     }
     56 
     57     int m=(l+r)>>1;
     58     if(x<=m) update(L[pr],L[rt],lson,x);//因为右边不需要更新,所以覆盖掉左边
     59     else     update(R[pr],R[rt],rson,x);
     60 }
     61 
     62 int query(int pr,int rt,int l,int r,int x)//查询l到r区间就是第r次插入减去第l-1次插入后的线段树的样子
     63 {
     64     if(l==r){
     65         return l;
     66     }
     67     //因为我们建立的是权值线段树,所以直接查找就可以
     68     int m=(l+r)>>1;
     69     int now=sum[L[rt]]-sum[L[pr]];//now为左子树新树-旧树
     70     if(now>=x) return query(L[pr],L[rt],lson,x);
     71     else       return query(R[pr],R[rt],rson,x-now);
     72 }
     73 
     74 int rt[maxn];
     75 
     76 int main()
     77 {
     78     int t;
     79     scanf("%d",&t);
     80     while(t--){
     81         scanf("%d%d",&n,&m);
     82         sz=0;
     83         for(int i=1;i<=n;i++){
     84             scanf("%d",&a[i]);
     85             b[i]=a[i];
     86         }
     87         sort(b+1,b+1+n);//首先把值全部排序去重,用于建权值线段树,权值线段树保存的内容是值的数量。
     88         int d=unique(b+1,b+1+n)-(b+1);
     89         build(rt[0],1,d);
     90         for(int i=1;i<=n;i++){//按照序列顺序插入值
     91             int x=lower_bound(b+1,b+1+d,a[i])-b;
     92             update(rt[i-1],rt[i],1,d,x);
     93         }
     94         for(int i=1;i<=m;i++){
     95             int l,r,k;
     96             scanf("%d%d%d",&l,&r,&k);
     97             printf("%d
    ",b[query(rt[l-1],rt[r],1,d,k)]);
     98         }
     99     }
    100     return 0;
    101 }

    你来到人间,就是要看看太阳,看看外面有趣的世界。

     
  • 相关阅读:
    网卡驱动引起openstack的mtu问题
    Ironic几种不同的场景下的网络拓扑
    enable multi-tenancy on openstack pike
    galera断电后无法重建集群
    Fabric单节点安装备忘
    OpenStack Ironic 常见问题
    Enable multi-tenancy on ironic
    kolla-ansible快速入门
    kolla管理openstack容器
    d2.js学习笔记(七)——动态SVG坐标空间
  • 原文地址:https://www.cnblogs.com/ZERO-/p/9806378.html
Copyright © 2011-2022 走看看