zoukankan      html  css  js  c++  java
  • 静态主席树,动态主席树(一种可持久化线段树)

    前置知识:

    动态开点

    study from:

    静态主席树:https://blog.csdn.net/a1351937368/article/details/78884526

    动态主席树:https://blog.csdn.net/WilliamSun0122/article/details/77885781

    原理:

    静态主席树

    1~i和1~i+1的相似性

    动态主席树

    树状数组

    记录变化

    得到1~i的结果

    时间上是两个log

    第一个log为树状数组(k->k-lowbit(k)->...)

    第二个log为每个数(k,k-lowbit(k),...)的线段树操作

    静态主席树

    https://www.luogu.org/problemnew/show/P3834

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <time.h>
      6 #include <string>
      7 #include <set>
      8 #include <map>
      9 #include <list>
     10 #include <stack>
     11 #include <queue>
     12 #include <vector>
     13 #include <bitset>
     14 #include <ext/rope>
     15 #include <algorithm>
     16 #include <iostream>
     17 using namespace std;
     18 #define ll long long
     19 #define minv 1e-6
     20 #define inf 1e9
     21 #define pi 3.1415926536
     22 #define nl 2.7182818284
     23 const ll mod=1e9+7;//998244353
     24 const int maxn=2e5+10;
     25 
     26 struct rec
     27 {
     28     int a,b;
     29 }f[maxn];
     30 
     31 struct node
     32 {
     33     int l,r,sum,number;
     34 }tr[maxn*20];
     35 
     36 int a[maxn],_index=0,value,tnum=0,result;
     37 int be[maxn],v[maxn];
     38 
     39 int cmp(rec a,rec b)
     40 {
     41     return a.a<b.a;
     42 }
     43 
     44 void ini_build(int l,int r)
     45 {
     46     tr[_index].sum=0;
     47     if (l==r)
     48     {
     49         tr[_index].l=0;
     50         tr[_index].r=0;
     51         tr[_index].number=++tnum;
     52     }
     53     else
     54     {
     55         int m=(l+r)>>1,cur=_index;
     56         tr[cur].l=++_index;
     57         ini_build(l,m);
     58 
     59         tr[cur].r=++_index;
     60         ini_build(m+1,r);
     61     }
     62 }
     63 
     64 void build(int l,int r,int pos)
     65 {
     66     if (l==r)
     67     {
     68         tr[_index].l=0;
     69         tr[_index].r=0;
     70         tr[_index].sum=tr[pos].sum+1;   ///not 1
     71         tr[_index].number=tr[pos].number;
     72     }
     73     else
     74     {
     75         int m=(l+r)>>1,cur=_index;
     76         tr[cur].sum=tr[pos].sum+1;
     77         if (value<=m)
     78         {
     79             tr[cur].l=++_index;
     80             tr[cur].r=tr[pos].r;
     81             build(l,m,tr[pos].l);
     82         }
     83         else
     84         {
     85             tr[cur].l=tr[pos].l;
     86             tr[cur].r=++_index;
     87             build(m+1,r,tr[pos].r);
     88         }
     89         tr[cur].sum=tr[tr[cur].l].sum+tr[tr[cur].r].sum;
     90     }
     91 }
     92 
     93 void query(int _indexl,int _indexr,int z)
     94 {
     95     if (tr[_indexl].l==0)
     96     {
     97         result=tr[_indexl].number;
     98         return;
     99     }
    100     if (tr[tr[_indexr].l].sum-tr[tr[_indexl].l].sum>=z)
    101         query(tr[_indexl].l,tr[_indexr].l,z);
    102     else
    103         query(tr[_indexl].r,tr[_indexr].r,z-tr[tr[_indexr].l].sum+tr[tr[_indexl].l].sum);
    104 }
    105 
    106 int main()
    107 {
    108     int n,m,i,num,x,y,z;
    109     scanf("%d%d",&n,&m);
    110     for (i=1;i<=n;i++)
    111     {
    112         scanf("%d",&f[i].a);
    113         f[i].b=i;
    114     }
    115     sort(f+1,f+n+1,cmp);
    116     num=0;
    117     f[0].a=2e9;
    118     for (i=1;i<=n;i++)
    119     {
    120         if (f[i].a!=f[i-1].a)
    121         {
    122             num++;
    123             v[num]=f[i].a;
    124         }
    125         a[f[i].b]=num;
    126     }
    127     be[0]=++_index;
    128     ini_build(1,num);
    129     for (i=1;i<=n;i++)
    130     {
    131         be[i]=++_index;
    132         value=a[i];
    133         build(1,num,be[i-1]);
    134     }
    135 
    136     while (m--)
    137     {
    138         scanf("%d%d%d",&x,&y,&z);
    139         query(be[x-1],be[y],z);
    140         printf("%d
    ",v[result],m);
    141     }
    142     return 0;
    143 }
    144 /*
    145 5 100
    146 1 5 1 5 5
    147 1 5 2
    148 1 5 3
    149 */

    动态主席树

    数值离散化

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=1e9+7;
     14 const int maxn=1e5+10;
     15 const int maxm=1e5+10;
     16 
     17 /**
     18 T*m*log(n)*log(value_range)
     19 1*1e5*17*18=
     20 **/
     21 
     22 /**
     23 离散化,减少范围
     24 可减少空间,时间
     25 
     26 1e9->1e5+1e5
     27 log
     28 30(actually slight larger)->18
     29 **/
     30 
     31 int maxv=1e5+1e5;
     32 
     33 struct node
     34 {
     35     int l,r,siz;
     36 }f[(maxn+maxm)*17*20];
     37 ///17:log(n) 20:log(value_range)
     38 
     39 int be[maxn],a[maxn],num[maxn],add[maxn],id;
     40 ///num: max log(n)*2
     41 
     42 int in[maxm][3];
     43 char in_mode[maxm][5];
     44 
     45 struct rec
     46 {
     47     int x,y;
     48     bool operator<(const rec &b) const
     49     {
     50         return x<b.x;
     51     }
     52 }ls[maxn+maxm];
     53 int value_rev[maxn+maxm];
     54 
     55 void update(int ind,int l,int r,int x,int y)
     56 {
     57     f[ind].siz+=y;
     58     if (l==r)   ///not l==x
     59         return;
     60     int m=(l+r)>>1;
     61     if (x<=m)
     62     {
     63         if (!f[ind].l)
     64         {
     65             f[ind].l=++id;
     66             f[id].l=f[id].r=f[id].siz=0;    ///init
     67         }
     68         update(f[ind].l,l,m,x,y);
     69     }
     70     else
     71     {
     72         if (!f[ind].r)
     73         {
     74             f[ind].r=++id;
     75             f[id].l=f[id].r=f[id].siz=0;    ///init
     76         }
     77         update(f[ind].r,m+1,r,x,y);
     78     }
     79 }
     80 
     81 int main()
     82 {
     83     char mode[5];
     84     int t,n,m,i,j,k,pos,g,l,r,v,M,cnt_ls;
     85     t=1;
     86 //    scanf("%d",&t);
     87     while (t--)
     88     {
     89 //        memset(f,0,sizeof(f));  ///or each point initialize
     90 
     91         scanf("%d%d",&n,&m);
     92         for (i=1;i<=n;i++)
     93         {
     94             be[i]=i;
     95             f[i].l=f[i].r=f[i].siz=0;
     96         }
     97         id=n;
     98 
     99         for (i=1;i<=n;i++)
    100         {
    101             scanf("%d",&a[i]);
    102             ls[i]={a[i],i};
    103         }
    104         cnt_ls=n;
    105         for (M=1;M<=m;M++)
    106         {
    107             scanf("%s",in_mode[M]);
    108             if (in_mode[M][0]=='Q')
    109                 scanf("%d%d%d",&in[M][0],&in[M][1],&in[M][2]);
    110             else
    111             {
    112                 scanf("%d%d",&in[M][0],&in[M][1]);
    113                 ls[++cnt_ls]={in[M][1],n+M};
    114             }
    115         }
    116 
    117         sort(ls+1,ls+cnt_ls+1);
    118         pos=0;
    119         ls[0].x=ls[1].x-1;
    120         for (i=1;i<=cnt_ls;i++)
    121         {
    122             if (ls[i].x!=ls[i-1].x)
    123             {
    124                 pos++;
    125                 value_rev[pos]=ls[i].x;
    126             }
    127             if (ls[i].y<=n)
    128                 a[ls[i].y]=pos;
    129             else
    130                 in[ls[i].y-n][1]=pos;
    131         }
    132 
    133         for (i=1;i<=n;i++)
    134         {
    135 //            scanf("%d",&a[i]);
    136             k=i;
    137             while (k<=n)
    138             {
    139                 update(be[k],1,maxv,a[i],1);
    140                 k+=k&-k;
    141             }
    142         }
    143 
    144         for (M=1;M<=m;M++)
    145 //        while (m--)
    146         {
    147 //            scanf("%s",mode);
    148             strcpy(mode,in_mode[M]);
    149             if (mode[0]=='Q')
    150             {
    151 //                scanf("%d%d%d",&i,&j,&pos);
    152                 i=in[M][0],j=in[M][1],pos=in[M][2];
    153                 g=0;
    154 
    155                 k=i-1;
    156                 while (k)
    157                 {
    158                     num[++g]=be[k];
    159                     add[g]=-1;
    160                     k-=k&-k;
    161                 }
    162 
    163                 k=j;
    164                 while (k)
    165                 {
    166                     num[++g]=be[k];
    167                     add[g]=1;
    168                     k-=k&-k;
    169                 }
    170 
    171                 l=1,r=maxv;///也可以设置叶子标志
    172                 while (l!=r)
    173                 {
    174                     v=0;
    175                     for (i=1;i<=g;i++)
    176                         v+=f[f[num[i]].l].siz*add[i];
    177                     if (v>=pos)
    178                     {
    179                         for (i=1;i<=g;i++)
    180                             num[i]=f[num[i]].l;
    181                         r=(l+r)>>1;
    182                     }
    183                     else
    184                     {
    185                         pos-=v;
    186                         for (i=1;i<=g;i++)
    187                             num[i]=f[num[i]].r;
    188                         l=((l+r)>>1)+1;
    189                     }
    190                 }
    191                 printf("%d
    ",value_rev[l]);
    192             }
    193             else
    194             {
    195 //                scanf("%d%d",&i,&j);
    196                 i=in[M][0],j=in[M][1];
    197 
    198                 k=i;
    199                 while (k<=n)
    200                 {
    201                     update(be[k],1,maxv,a[i],-1);
    202                     update(be[k],1,maxv,j,1);
    203                     k+=k&-k;
    204                 }
    205                 a[i]=j;
    206             }
    207         }
    208     }
    209 
    210     return 0;
    211 }
    212 /*
    213 1
    214 5 13
    215 100000000 100000000 100000000 100000000 100000000
    216 Q 1 5 1
    217 Q 1 5 2
    218 Q 1 5 3
    219 Q 1 5 4
    220 Q 1 5 5
    221 C 3 10123445
    222 Q 1 5 1
    223 Q 1 5 2
    224 Q 1 5 3
    225 Q 1 5 4
    226 Q 1 5 5
    227 Q 2 2 1
    228 Q 3 3 1
    229 */

    不离散化,TLE了

    ==============================

    不同的数据范围

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112

    使用上述方法,会超空间

    空间优化:

    读入a[1]~a[n],

    使用静态主席树的方式建树

    n[5e4]*log(value_range)[18]

    然后对于每个询问(与之前一样)

    m[1e4]*2[修改数字,删除原来,增加现在]*log(n)[16]*log(value_range)[18]

    即使优化了,然而还是会超空间的,感觉数据不严谨。

  • 相关阅读:
    python day6
    python day5
    python基础晋级篇
    python基础篇
    初识Python
    if语句
    A22. openstack架构实战-openstack的api
    A21. openstack架构实战-配置三层网络vxlan
    A20. openstack架构实战-虚拟机创建的流程
    A19. openstack架构实战-云主机的冷迁移
  • 原文地址:https://www.cnblogs.com/cmyg/p/9607334.html
Copyright © 2011-2022 走看看