zoukankan      html  css  js  c++  java
  • 主席树

    https://blog.csdn.net/qq_39653331/article/details/78816987

    https://www.cnblogs.com/zyf0163/p/4749042.html

    感觉都写的好好,但是还是没有完全弄懂,目前只是懂了一点点QAQ,还是太菜了

    然后贴上最近刷的几道题的代码吧

    hdu 4417 Super Mario

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 #define N 100005
     8 
     9 int root[N];//root[i]表示第i课线段树
    10 int size[N*25],lchild[N*25],rchild[N*25];
    11 int tot;
    12 
    13 void insert(int last,int cur,int L,int R,int k) //单点更新
    14 {
    15     size[cur]=size[last]+1;//将前一个树的信息复制过来
    16     lchild[cur]=lchild[last];
    17     rchild[cur]=rchild[last];
    18     if(L==R)return ;
    19     int mid=L+R>>1;
    20     if(k<=mid) insert(lchild[last],lchild[cur]=++tot,L,mid,k);//对于需要更改的节点都需要新增节点
    21     else insert(rchild[last],rchild[cur]=++tot,mid+1,R,k);
    22 }
    23 int query(int last,int cur,int l,int r,int L,int R)
    24 {
    25     if(l>r)return 0;
    26     if(L==l&&r==R){
    27         return size[cur]-size[last];
    28     }
    29     int mid=(L+R)>>1;
    30     if(l>mid)return query(rchild[last],rchild[cur],l,r,mid+1,R);
    31     else if(r<=mid)return query(lchild[last],lchild[cur],l,r,L,mid);
    32     else return query(rchild[last],rchild[cur],mid+1,r,mid+1,R)+query(lchild[last],lchild[cur],l,mid,L,mid);
    33 }
    34 int a[100005];
    35 int b[100005];
    36 int main(){
    37     int t;
    38     scanf("%d",&t);
    39     int c=1;
    40     while(t--){
    41         int n,m;
    42         scanf("%d%d",&n,&m);
    43         for(int i=1;i<=n;i++){
    44             scanf("%d",&a[i]);
    45             b[i]=a[i];
    46         }
    47         sort(b+1,b+n+1);//排序
    48         int nn=unique(b+1,b+n+1)-b-1;//去重
    49         //上面是在离散化处理
    50         tot=0;
    51         for(int i=1;i<=n;i++){
    52             int k=lower_bound(b+1,b+nn+1,a[i])-b;//找到a[i]在整个数列中是第几大
    53             insert(root[i-1],root[i]=++tot,1,nn,k);
    54         }
    55         printf("Case %d:
    ",c++);
    56         for(int i=1;i<=m;i++){
    57             int l,r,h;
    58             scanf("%d%d%d",&l,&r,&h);
    59             l++;r++;
    60             int k=upper_bound(b+1,b+1+nn,h)-b-1;//找到h在整个数列中是第几大
    61             printf("%d
    ",query(root[l-1],root[r],1,k,1,nn));
    62         }
    63     }
    64     return 0;
    65 }

    P3567 [POI2014]KUR-Couriers

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 using namespace std;
     6 const int N=5e5+6;
     7 int n,m,cnt,root[N],a[N],x,y,k;
     8 struct node
     9 {
    10     int l,r,sum;
    11 }T[N*40];
    12 vector<int>v;
    13 int getid(int x)
    14 {
    15     return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
    16 }
    17 void update(int l,int r,int &x,int y,int pos)
    18 {
    19     T[++cnt]=T[y];
    20     T[cnt].sum++;
    21     x=cnt;
    22     if(l==r)
    23         return ;
    24     int mid=(l+r)>>1;
    25     if(mid>=pos)
    26         update(l,mid,T[x].l,T[y].l,pos);
    27     else
    28         update(mid+1,r,T[x].r,T[y].r,pos);
    29 }
    30 int query(int l,int r,int x,int y,int k)
    31 {
    32     if(l==r)
    33         return l;
    34     int mid=(l+r)>>1;
    35     int sum1=T[T[y].l].sum-T[T[x].l].sum;
    36     int sum2=T[T[y].r].sum-T[T[x].r].sum;
    37     if(sum1+sum1>k)
    38         return query(l,mid,T[x].l,T[y].l,k);
    39     if(sum2+sum2>k)
    40         return query(mid+1,r,T[x].r,T[y].r,k);
    41     return 0;
    42 }
    43 int main()
    44 {
    45     scanf("%d%d",&n,&m);
    46     for(int i=1;i<=n;i++)
    47     {
    48         scanf("%d",&a[i]);
    49         update(1,n,root[i],root[i-1],a[i]);
    50     }
    51     for(int i=1;i<=m;i++)
    52     {
    53         scanf("%d%d",&x,&y);
    54         printf("%d
    ",query(1,n,root[x-1],root[y],y-x+1));
    55     }
    56     return 0;
    57 }

    POJ 2104 K-th Number 主席树

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 using namespace std;
     6 const int N=1e5+6;
     7 int n,m,cnt,root[N],a[N],x,y,k;
     8 struct node
     9 {
    10     int l,r,sum;
    11 }T[N*40];
    12 vector<int>v;
    13 int getid(int x)
    14 {
    15     return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
    16 }
    17 void update(int l,int r,int &x,int y,int pos)
    18 {
    19     T[++cnt]=T[y];
    20     T[cnt].sum++;
    21     x=cnt;
    22     if(l==r)
    23         return ;
    24     int mid=(l+r)>>1;
    25     if(mid>=pos)
    26         update(l,mid,T[x].l,T[y].l,pos);
    27     else
    28         update(mid+1,r,T[x].r,T[y].r,pos);
    29 }
    30 int query(int l,int r,int x,int y,int k)
    31 {
    32     if(l==r)
    33         return l;
    34     int mid=(l+r)>>1;
    35     int sum=T[T[y].l].sum-T[T[x].l].sum;
    36     if(sum>=k)
    37         return query(l,mid,T[x].l,T[y].l,k);
    38     else
    39         return query(mid+1,r,T[x].r,T[y].r,k-sum);
    40 }
    41 int main()
    42 {
    43     scanf("%d%d",&n,&m);
    44     for(int i=1;i<=n;i++)
    45     {
    46         scanf("%d",&a[i]);
    47         v.push_back(a[i]);
    48     }
    49     sort(v.begin(),v.end());
    50     v.erase(unique(v.begin(),v.end()),v.end());
    51     for(int i=1;i<=n;i++)
    52     {
    53         update(1,n,root[i],root[i-1],getid(a[i]));
    54     }
    55     for(int i=1;i<=m;i++)
    56     {
    57         scanf("%d%d%d",&x,&y,&k);
    58         printf("%d
    ",v[query(1,n,root[x-1],root[y],k)-1]);
    59     }
    60     return 0;
    

    主席树模板

      1 #include <bits/stdc++.h>
      2 using namespace std ;
      3 bool Read ( int &x ) ///输入挂
      4 {
      5     char c = getchar() ; x = 0 ; bool f = 0 ;
      6     while ( !isdigit(c) )
      7     {
      8         if ( c == '-' ) f = 1 ;
      9         if ( c == EOF ) return false ; c = getchar() ;
     10     }
     11     while ( isdigit(c) )
     12     { x = 10 * x + c - '0' ; c = getchar() ; }
     13     if (f) x = -x ;return true ;
     14 }
     15 void Print ( int x ) ///输出挂
     16 {
     17     int len=0,a[50] ;
     18     if ( x == 0 ) { putchar('0') ; return ; }
     19     if ( x < 0 ) { putchar('-') ; x = -x ; }
     20     while (x) { a[++len] = x%10 ; x /= 10 ; }
     21     while (len) putchar(a[len--]+'0') ;
     22 }
     23 
     24 const int maxn=200010 ;
     25 int n,m,rt[maxn],Rank[maxn],cnt ;
     26 struct node
     27 {
     28     int l, r, v ;
     29 } tree[maxn<<5] ;
     30 struct nodd
     31 {
     32     int v, id ;
     33     friend bool operator < ( nodd a, nodd b )
     34     {
     35         return a.v == b.v ? a.id < b.id : a.v < b.v ;
     36     }
     37 } a[maxn] ;
     38 ///这个k是数据key,不是第k大,x前面有一个取地址
     39 void insert ( int K, int& x, int l, int r )
     40 {///这个是调用过程:insert(Rank[i],rt[i],1,n) ;
     41     tree[++cnt]=tree[x] ;
     42     x=cnt;///把rt[i]指向了rt[++cnt]这个真的根节点
     43     tree[x].v++;///增加数量
     44     int mid =(l+r)>>1 ;
     45     if(l==r)return ;
     46     if(K<=mid) insert(K,x[tree].l,l,mid) ;
     47     else insert(K,x[tree].r,mid+1,r) ;///节点的编号机制不是*2和*2+1
     48     ///而是根据调用次数由cnt管控,所以要存在每一个节点里
     49 }
     50 
     51 int query ( int rt1, int rt2, int l, int r, int K )
     52 {
     53     if ( l == r ) return l ;
     54     int mid = l+r >> 1 ;
     55     int num = tree[rt2].l[tree].v - tree[rt1].l[tree].v ;
     56     /**可加减性,为啥这样做,因为几点存的是前缀和,
     57     我们要特定区间就把前面的减去咯。
     58     你也可以这样认为:假设查第999大,当前节点总共管3个数,
     59     你就需要把前面没用的减去咯。*/
     60     if ( K <= num )
     61         return query ( rt1[tree].l, rt2[tree].l, l, mid, K ) ;
     62     else
     63         return query ( rt1[tree].r, rt2[tree].r, mid+1, r, K-num ) ;
     64 }
     65 
     66 int main()
     67 {
     68     int i,j,k,x,y;
     69     Read(n) ; Read(m) ;
     70     for (i=1;i<=n;i++) ///离散
     71     {
     72         Read(a[i].v) ;
     73         a[i].id=i ;
     74     }
     75     sort (a+1,a+n+1) ;
     76     for (i=1;i<=n;i++)
     77         Rank[a[i].id]=i ;
     78 
     79     for (i=1;i<=n;i++)
     80     {
     81         rt[i]=rt[i-1] ;
     82         /**
     83         一开始有棵空树,不这样写,直接传root[1],
     84         当需要递归到不需要改的区间,无法找到初试树的位置,
     85         所以暂且把初试树的root完全复制过来
     86         这样,因为每一棵树的根节点存储了它儿子的标号,
     87         所以这一步相当于第1棵树完全等价与第0棵树,
     88         只多开了一个root,其他的已经!!完全检索!!到上一棵树里
     89         然后在新的树里把不一样的树枝修改成新的值,
     90         并且新开空间就行了
     91         所以之后递归就是if,else if,只选择一条路,
     92         以此类推,第i棵树继承第i-1棵树就行了
     93         */
     94         insert(Rank[i],rt[i],1,n);
     95     }
     96 
     97     while(m--)
     98     {
     99         Read(x);Read(y);Read(k) ;
    100         Print(a[query(rt[x-1],rt[y],1,n,k)].v ) ;
    101         putchar('
    ') ;
    102     }
    103 
    104     return 0 ;
    105 }
  • 相关阅读:
    MySQL 如何只导出 指定的表 的表结构和数据 ( 转 )
    速度之王 — LZ4压缩算法(三)
    lz4,pigz,gzip 3者比较
    用php实现百度网盘图片直链的代码分享
    hibernate的oracle配置(转)
    过滤器
    dom4j创建格式化的xml文件
    jstl表达式
    jsp内置对象和el表达式
    jsp 三大指令和动作标签
  • 原文地址:https://www.cnblogs.com/acm-cyz/p/11516981.html
Copyright © 2011-2022 走看看