• HDU 4251 --- 主席树(划分树是正解)


    题意:查询区间中位数

    思路:模板题,相当于区间第K大的数,主席树可以水过,但划分树是正解。但还没搞明白划分树,先上模板

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <cstdlib>
      6 #include <string>
      7 #include <vector>
      8 #include <algorithm>
      9 #include <set>
     10 #define repu(i,a,b) for(int i=a;i<b;i++)
     11 using namespace std;
     12 #define N 1000010
     13 #define ll long long
     14 #define _cle(m, a) memset(m, a, sizeof(m))
     15 const int MAXN = 100010;
     16 const int M = MAXN * 30;
     17 int n,q,m,tot;
     18 int a[MAXN], t[MAXN];
     19 int T[MAXN], lson[M], rson[M], c[M];
     20 void Init_Hash()
     21 {
     22     for(int i = 1; i <= n; i++)
     23         t[i] = a[i];
     24     sort(t+1,t+1+n);
     25     m = unique(t+1,t+1+n) -t-1;
     26 }
     27 int build(int l, int r)
     28 {
     29     int root = tot++;
     30     c[root] = 0;
     31     if(l != r)
     32     {
     33         int mid = (l+r)>>1;
     34         lson[root] = build(l,mid);
     35         rson[root] = build(mid+1,r);
     36     }
     37     return root;
     38 }
     39 int Hash(int x)
     40 {
     41     return lower_bound(t+1,t+1+m,x) - t;
     42 }
     43 int update(int root, int pos, int val)
     44 {
     45     int newroot = tot++, tmp = newroot;
     46     c[newroot] = c[root] + val;
     47     int l = 1, r = m;
     48     while(l < r)
     49     {
     50         int mid = (l+r)>>1;
     51         if(pos <= mid)
     52         {
     53             lson[newroot] = tot++;
     54             rson[newroot] = rson[root];
     55             newroot = lson[newroot];
     56             root = lson[root];
     57             r = mid;
     58         }
     59         else
     60         {
     61             rson[newroot] = tot++;
     62             lson[newroot] = lson[root];
     63             newroot = rson[newroot];
     64             root = rson[root];
     65             l = mid+1;
     66         }
     67         c[newroot] = c[root] + val;
     68     }
     69     return tmp;
     70 }
     71 int query(int left_root, int right_root, int k)
     72 {
     73     int l = 1, r = m;
     74     while( l < r)
     75     {
     76         int mid = (l+r)>>1;
     77         if(c[lson[left_root]] -c[lson[right_root]] >= k )
     78         {
     79             r = mid;
     80             left_root = lson[left_root];
     81             right_root = lson[right_root];
     82         }
     83         else
     84         {
     85             l = mid + 1;
     86             k -= c[lson[left_root]] - c[lson[right_root]];
     87             left_root = rson[left_root];
     88             right_root = rson[right_root];
     89         }
     90     }
     91     return l;
     92 }
     93 int main()
     94 {
     95 //freopen("in.txt","r", stdin);
     96 //freopen("out.txt","w", stdout);
     97     int kase = 1;
     98     while(scanf("%d",&n) == 1)
     99     {
    100         tot = 0;
    101         for(int i = 1; i <= n; i++)
    102             scanf("%d",&a[i]);
    103         Init_Hash();
    104         T[n+1] = build(1,m);
    105         for(int i = n; i ; i--)
    106         {
    107             int pos = Hash(a[i]);
    108             T[i] = update(T[i+1],pos,1);
    109         }
    110         printf("Case %d:
    ",kase++);
    111         scanf("%d",&q);
    112         while(q--)
    113         {
    114             int l,r,k;
    115             scanf("%d%d",&l,&r);
    116             k = (r-l)/2+1;
    117             printf("%d
    ",t[query(T[l],T[r+1],k)]);
    118         }
    119     }
    120     return 0;
    121 }
    主席树

    先上KB模板

     1 //划分树
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int MAXN=100010;
     7 int tree[20][MAXN];//表示每层每个位置的值
     8 int sorted[MAXN];//已经排序好的数
     9 int toleft[20][MAXN];//toleft[p][i]表示第i层从1到i有数分入左边
    10 void build(int l,int r,int dep){
    11     if(l==r)return;
    12     int mid=(l+r)>>1;
    13     int same=mid-l+1;//表示等于中间值而且被分入左边的个数
    14     for(int i=l;i<=r;i++)//注意是l,不是one
    15         if(tree[dep][i]<sorted[mid]) same--;
    16     int lpos=l;
    17     int rpos=mid+1;
    18     for(int i=l;i<=r;i++){
    19         if(tree[dep][i]<sorted[mid]) tree[dep+1][lpos++]=tree[dep][i];
    20         else if(tree[dep][i]==sorted[mid]&&same>0){
    21             tree[dep+1][lpos++]=tree[dep][i];
    22             same--;
    23         }
    24         else tree[dep+1][rpos++]=tree[dep][i];
    25         toleft[dep][i]=toleft[dep][l-1]+lpos-l;
    26     }
    27     build(l,mid,dep+1);
    28     build(mid+1,r,dep+1);
    29 }
    30 //查询区间第k大的数,[L,R]是大区间,[l,r]是要查询的小区间
    31 int query(int L,int R,int l,int r,int dep,int k){
    32     if(l==r)return tree[dep][l];
    33     int mid=(L+R)>>1;
    34     int cnt=toleft[dep][r]-toleft[dep][l-1];
    35     if(cnt>=k){
    36         int newl=L+toleft[dep][l-1]-toleft[dep][L-1];int newr=newl+cnt-1;
    37         return query(L,mid,newl,newr,dep+1,k);
    38     }
    39     else{
    40         int newr=r+toleft[dep][R]-toleft[dep][r],newl=newr-(r-l-cnt);
    41         return query(mid+1,R,newl,newr,dep+1,k-cnt);
    42     }
    43 }
    44 int main(){
    45     int n,m,t=0;
    46     while(~scanf("%d",&n)){
    47         memset(tree,0,sizeof(tree));
    48         for(int i=1;i<=n;i++){
    49             scanf("%d",&tree[0][i]);
    50             sorted[i]=tree[0][i];
    51         }
    52         sort(sorted+1,sorted+n+1);
    53         build(1,n,0);
    54         scanf("%d",&m);
    55         printf("Case %d:
    ",++t);
    56         int s,t,k;
    57         while(m--){
    58             scanf("%d%d",&s,&t);
    59             k=(t-s+2)/2;
    60             printf("%d
    ",query(1,n,s,t,0,k));
    61         }
    62     }
    63     return 0;
    64 }
    划分树
  • 相关阅读:
    [LCA] 最近公共祖先
    [DP] D. Beautiful Array
    [模板] [拓扑序列]
    [模板] 区间筛素数
    [DP] 简单的烦恼
    [贪心] 二元组最小值最大
    [模板] 树状数组及其应用
    [Trie] 最大异或对
    [模板][二分]倍增及其应用
    ios学习记录 day31 UI 9 多视图切换 导航控制器
  • 原文地址:https://www.cnblogs.com/ACMERY/p/4507196.html
Copyright © 2020-2023  润新知