zoukankan      html  css  js  c++  java
  • POJ 2104 划分树

    划分树:查询区间第K大

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 #define clc(a,b) sizeof(a,b,sizeof(a))
     6 using namespace std;
     7 const int maxn=222;
     8 const int MAXN = 100010;
     9 int tree[20][MAXN];
    10 int sorted[MAXN];
    11 int toleft[20][MAXN];
    12 
    13 void build(int l,int r,int dep) {
    14     if(l==r)
    15         return;
    16     int mid=(l+r)>>1;
    17     int same= mid-l+1;
    18     for(int i=l; i<=r; i++) {
    19         if(tree[dep][i]<sorted[mid]) {
    20             same--;
    21         }
    22     }
    23     int lpos=l;
    24     int rpos=mid+1;
    25     for(int i=l; i<=r; i++) {
    26         if(tree[dep][i]<sorted[mid])
    27             tree[dep+1][lpos++]=tree[dep][i];
    28         else if(tree[dep][i]==sorted[mid]&&same>0) {
    29             tree[dep+1][lpos++]=tree[dep][i];
    30             same--;
    31         } else
    32             tree[dep+1][rpos++]=tree[dep][i];
    33         toleft[dep][i]=toleft[dep][l-1]+lpos-l;
    34     }
    35     build(l,mid,dep+1);
    36     build(mid+1,r,dep+1);
    37 }
    38 
    39 int query(int L,int R,int l,int r,int dep,int k) {
    40     if(l==r) return tree[dep][l];
    41     int mid=(L+R)>>1;
    42     int cnt=toleft[dep][r]-toleft[dep][l-1];
    43     if(cnt>=k) {
    44         int newl=L+toleft[dep][l-1]-toleft[dep][L-1];
    45         int newr=newl+cnt-1;
    46         return query(L,mid,newl,newr,dep+1,k);
    47     } else {
    48         int newr=r+toleft[dep][R]-toleft[dep][r];
    49         int newl=newr-(r-l-cnt);
    50         return query(mid+1,R,newl,newr,dep+1,k-cnt);
    51     }
    52 }
    53 
    54 int main() {
    55     int n,m;
    56     while(scanf("%d%d",&n,&m)==2) {
    57         clc(tree,0);
    58         for(int i=1; i<=n; i++) {
    59             scanf("%d",&tree[0][i]);
    60             sorted[i]=tree[0][i];
    61         }
    62         sort(sorted+1,sorted+1+n);
    63         build(1,n,0);
    64         int s,t,k;
    65         while(m--) {
    66             scanf("%d%d%d",&s,&t,&k);
    67             printf("%d
    ",query(1,n,s,t,0,k));
    68         }
    69     }
    70     return 0;
    71 }
    View Code

    还有另外一种模板,记录比当前元素还小的元素和。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 #define clc(a,b) sizeof(a,b,sizeof(a))
     6 #define LL long long
     7 using namespace std;
     8 const int N=1e5+5;
     9 int p;
    10 LL sum=0;
    11 int sorted[N];            //对原来集合中的元素排序后的值
    12 struct node {
    13     int valu[N];       //val记录第k层当前位置元素的值
    14     int num[N];                //num记录元素所在区间的当前位置之前进入左孩子的个数
    15     LL sum[N];        //sum记录比当前元素小的元素的和
    16 } t[20];
    17 
    18 void build(int lft,int rht,int ind) {
    19     if(lft==rht) return;
    20     int mid=lft+(rht-lft)>>1;
    21     int isame=mid-lft+1,same=0;
    22     /* isame用来标记和中间值val_mid相等的,且分到左孩子的数的个数
    23        初始时,假定当前区间[lft,rht]有mid-lft+1个和valu_mid相等。
    24        先踢掉中间值小的,剩下的就是要插入到左边的
    25      */
    26     for(int i=lft; i<=rht; i++)
    27         if(t[ind].valu[i]<sorted[mid]) isame--;
    28     int ln=lft,rn=mid+1;
    29     for(int i=lft; i<=rht; i++) {
    30         if(i==lft) {    //初始一个子树
    31             t[p].num[i]=0;
    32             t[p].sum[i]=0;
    33         } else {        //初始区间下一个节点
    34             t[p].num[i]=t[p].num[i-1];
    35             t[p].sum[i]=t[p].sum[i-1];
    36         }
    37         /* 如果大于,肯定进入右孩子,否则判断是否还有相等的应该进入左孩子的,
    38            没有,直接进入右孩子,否则进入左孩子,同时更新节点的sum域和num域
    39          */
    40         if(t[p].valu[i]<sorted[mid]) {
    41             t[p].num[i]++;
    42             t[p].sum[i]+=t[p].valu[i];
    43             t[p+1].valu[ln++]=t[p].valu[i];
    44         } else if(t[p].valu[i]>sorted[mid])
    45             t[p+1].valu[rn++]=t[p].valu[i];
    46         else {
    47             if(same<isame) {
    48                 same++;
    49                 t[p].num[i]++;
    50                 t[p].sum[i]+=t[p].valu[i];
    51                 t[p+1].valu[ln++]=t[p].valu[i];
    52             } else {
    53                 t[p+1].valu[rn++]=t[p].valu[i];
    54             }
    55         }
    56     }
    57     build(lft,mid,ind+1);
    58     build(mid+1,rht,ind+1);
    59 }
    60 
    61 int query(int a,int b,int k,int p,int lft,int rht) {
    62     if(lft==rht) return t[p].valu[a];
    63     /*到达叶子结点就找到该元素,返回
    64     S 记录区间[a,b]中进入左孩子的元素的个数
    65     SS 记录区间[lft,a-1]中进入左孩子的元素的个数
    66     SSS 记录区间[a,b]中小于第k大的元素的值和
    67     B2 表示[lft,a-1]中分到右孩子的个数
    68     BB 表示[a,b]中分到右孩子的个数
    69     */
    70     int s,ss,b2,bb,mid=lft+(rht-lft)/2;
    71     double sss=0;
    72     if(a==lft) { //端点重合的情况,单独考虑
    73         s = t[p].num[b];
    74         ss = 0;
    75         sss = t[p].sum[b];
    76     } else {
    77         s = t[p].num[b] - t[p].num[a-1];
    78         ss = t[p].num[a-1];
    79         sss = t[p].sum[b] - t[p].sum[a-1];
    80     }
    81     if(s>=k) {    //进入左孩子,同时更新区间端点值。
    82         a = lft + ss;//
    83         b = lft + ss + s - 1;
    84         return query(a, b, k, p+1, lft, mid);
    85     } else {
    86         bb = a - lft - ss;
    87         b2 = b - a - 1 - s;
    88         a = mid + bb + 1;
    89         b = mid + bb + b2;
    90         sum += sss;
    91         return query(a,b,k-s,p+1,mid+1,rht);
    92     }
    93 }
    View Code
  • 相关阅读:
    [APM] OneAPM 云监控部署与试用体验
    Elastic Stack 安装
    xBIM 综合使用案例与 ASP.NET MVC 集成(一)
    JQuery DataTables Selected Row
    力导向图Demo
    WPF ViewModelLocator
    Syncfusion SfDataGrid 导出Excel
    HTML Table to Json
    .net core 2.0 虚拟目录下载 Android Apk 等文件
    在BootStrap的modal中使用Select2
  • 原文地址:https://www.cnblogs.com/ITUPC/p/5277257.html
Copyright © 2011-2022 走看看