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
  • 相关阅读:
    A component required a bean named xxx that could not be found. Action: Consider defining
    jmeter 配置csv 登陆网站 报错
    动手动脑(文件与流)
    java异常处理总结
    动手动脑(异常处理)
    动手动脑(继承与多态)
    查询对象个数
    动手动脑
    动手动脑
    统计英语文章的单词
  • 原文地址:https://www.cnblogs.com/ITUPC/p/5277257.html
Copyright © 2011-2022 走看看