zoukankan      html  css  js  c++  java
  • poj 2104 K-th Number (划分树入门 或者 主席树入门)

    题意:给n个数,m次询问,每次询问L到R中第k小的数是哪个

    算法1:划分树

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 using namespace std;
     6 
     7 const int mx=1e5+5;
     8 int tree[30][mx];
     9 int sortt[mx];
    10 int sum[30][mx];
    11 
    12 void build(int l,int r,int c)
    13 {
    14     if (l==r) return ;
    15     int m=(l+r)>>1;
    16     int isame=m-l+1;
    17     int pl=l,pr=m+1;
    18     for (int i=l;i<m;i++)
    19         if (tree[c][i]<sortt[m]) isame--;
    20     for (int i=l;i<=r;i++){
    21         if (i==l) sum[c][i]=0;
    22         else sum[c][i]=sum[c][i-1];
    23         if (tree[c][i]<sortt[m]){
    24             tree[c+1][pl++]=tree[c][i];
    25             sum[c][i]++;
    26         }
    27         else if ( tree[c][i]==sortt[m]&&isame){
    28             isame--;
    29             tree[c+1][pl++]=tree[c][i];
    30             sum[c][i]++;
    31         }
    32         else tree[c+1][pr++]=tree[c][i];
    33     }
    34     build(l,m,c+1);
    35     build(m+1,r,c+1);
    36 }
    37 
    38 int query(int L,int R,int l,int r,int c,int k){
    39     if (L==R) return tree[c][L];
    40     int s,ss;
    41     if (l==L){
    42         s=0;
    43         ss=sum[c][r];
    44     }
    45     else{
    46         s=sum[c][l-1];
    47         ss=sum[c][r]-s;
    48     }
    49     int m=(L+R)>>1;
    50     if (k<=ss) return query(L,m,L+s,L+s+ss-1,c+1,k);
    51     return query(m+1,R,m+1+l-L-s,m+1+r-L-s-ss,c+1,k-ss);
    52 }
    53 
    54 int main(){
    55     int n,m;
    56     scanf("%d%d",&n,&m);
    57     for (int i=1;i<=n;i++){
    58         scanf("%d",&sortt[i]);
    59         tree[0][i]=sortt[i];
    60     }
    61     sort(sortt+1,sortt+1+n);
    62     build(1,n,0);
    63     while (m--)
    64     {
    65         int l,r,k;
    66         scanf("%d%d%d",&l,&r,&k);
    67         printf("%d
    ",query(1,n,l,r,0,k));
    68     }
    69 
    70 }

     算法2:主席树

     1 /*************************************************************
     2 算法:主席树
     3 思想:建n+1棵线段树,每颗线段数结构都是一样,先建一棵空树,然
     4       后每棵树都在前一棵树的基础上进行修改。
     5       把样例按照代码模拟一遍,就很容易理解了。
     6 **************************************************************/
     7 #include<cstdio>
     8 #include<cstring>
     9 #include<algorithm>
    10 #include<iostream>
    11 #include<vector>
    12 using namespace std;
    13 
    14 const int mx=1e5+5;
    15 struct Tree        ///树的节点
    16 {
    17     int l,r;      ///树的区间
    18     int ls,rs;    ///树的左右孩子
    19     int sum;
    20 };
    21 Tree tree[mx*20];
    22 int a[mx],b[mx];
    23 int s[mx],cnt;
    24 
    25 void build(int l,int r,int &node)   ///建空树,和线段树差不多
    26 {
    27     node=++cnt;
    28     tree[node].l=l;
    29     tree[node].r=r;
    30     tree[node].sum=0;
    31     if (l==r) return ;
    32     int m=(l+r)/2;
    33     build(l,m,tree[node].ls);
    34     build(m+1,r,tree[node].rs);
    35 }
    36 
    37 void inser(int n1,int &n2,int pos)  ///在上一棵树的基础上建立新树
    38 {
    39     n2=++cnt;
    40     tree[n2].l=tree[n1].l;     ///区间和上一棵树一样
    41     tree[n2].r=tree[n1].r;
    42     tree[n2].rs=tree[n1].rs;   ///保证没有修改的部分和上一棵树一样
    43     tree[n2].ls=tree[n1].ls;
    44     tree[n2].sum=tree[n1].sum+1;
    45     if (tree[n1].l==tree[n1].r) return ;
    46     int m=(tree[n1].l+tree[n1].r)/2;
    47     if (pos<=m) inser(tree[n1].ls,tree[n2].ls,pos);
    48     else inser(tree[n1].rs,tree[n2].rs,pos);
    49 }
    50 
    51 int query(int n1,int n2,int k)    ///查询的k小的树
    52 {
    53     if (tree[n1].l==tree[n1].r)
    54     {
    55         return b[tree[n1].l];
    56     }
    57     int cut=tree[tree[n2].ls].sum-tree[tree[n1].ls].sum;
    58     if (cut>=k) return query(tree[n1].ls,tree[n2].ls,k);
    59     return query(tree[n1].rs,tree[n2].rs,k-cut);
    60 }
    61 
    62 int main()
    63 {
    64     int n,m;
    65     scanf("%d%d",&n,&m);
    66     for (int i=1;i<=n;i++)
    67     {
    68         scanf("%d",&a[i]);
    69         b[i]=a[i];
    70     }
    71     sort(b+1,n+b+1);
    72     cnt=0;
    73     build(1,n,s[0]);
    74     for (int i=1;i<=n;i++)
    75     {
    76         int pos=lower_bound(b+1,b+n+1,a[i])-b; ///找的a[i]要放的位置
    77         inser(s[i-1],s[i],pos);
    78     }
    79     while (m--)
    80     {
    81         int l,r,k;
    82         scanf("%d%d%d",&l,&r,&k);
    83         printf("%d
    ",query(s[l-1],s[r],k));
    84     }
    85 }
  • 相关阅读:
    matlab中s函数编写心得-转自水木
    webgl编程指南笔记【一】
    node辅助工具npm、yarn、nrm、n、Nodemon
    es6复习笔记
    游戏客户端开发劝退
    一步步搭建现代前端框架(三)
    一步步搭建现代前端框架(二)
    一步步搭建现代前端框架(一)
    vue 生命周期钩子 路由钩子 动画钩子 执行顺序
    怎样提升手机相机照片效果
  • 原文地址:https://www.cnblogs.com/pblr/p/5929049.html
Copyright © 2011-2022 走看看