zoukankan      html  css  js  c++  java
  • 【复习笔记】主席树

    昨天在写带修改主席树的时候,咸鱼zcysky发现自己似乎根本不会写主席树

    于是正好找个空复习下……

    主席树的原理不用我扯了,主席树为啥能求k大,大概在它可以用历史版本存下区间的前缀和,求的时候差分下就能提出我要求的区间。

    不过这么搞的话不要忘了离散化。

    1.kth number

    就是上面的裸题,不要手贱写bits就好。

     1 #include<iostream>
     2 #include<cstdio>
     3 #define N 100010
     4 #include<algorithm>
     5 #include<cstring>
     6 using namespace std;
     7 struct Node{int sum,ls,rs;}T[N*20];
     8 int cnt;
     9 void ins(int &num,int &x,int l,int r){
    10     T[cnt++]=T[x];x=cnt-1;T[x].sum++;
    11     if(l==r)return;
    12     int mid=(l+r)/2;
    13     if(num<=mid)ins(num,T[x].ls,l,mid);
    14     else ins(num,T[x].rs,mid+1,r); 
    15 }
    16 int query(int i,int j,int k,int l,int r){
    17     if(l==r)return l;
    18     int t=T[T[j].ls].sum-T[T[i].ls].sum;
    19     int mid=(l+r)/2;
    20     if(k<=t)return query(T[i].ls,T[j].ls,k,l,mid);
    21     else return query(T[i].rs,T[j].rs,k-t,mid+1,r);
    22 }
    23 struct A{
    24     int x,idx;
    25     bool operator<(const A &s)const{
    26         return x<s.x;}
    27 };
    28 A a[N];
    29 int rank[N],root[N];
    30 int n,m;
    31 int main(){
    32     T[0].ls=T[0].rs=T[0].sum=0;root[0]=0;
    33     while(scanf("%d%d",&n,&m)!=EOF){
    34         for(register int i=1;i<=n;++i){
    35             scanf("%d",&a[i].x);
    36             a[i].idx=i;
    37         }
    38         sort(a+1,a+n+1);
    39         for(int i=1;i<=n;i++)rank[a[i].idx]=i;
    40         cnt=1;
    41         for(int i=1;i<=n;i++){
    42             root[i]=root[i-1];
    43             ins(rank[i],root[i],1,n);
    44         }
    45         while(m--){
    46             int i,j,k;
    47             scanf("%d%d%d",&i,&j,&k);
    48             int ans=a[query(root[i-1],root[j],k,1,n)].x;
    49             printf("%d
    ",ans);
    50         }
    51     }
    52     return 0;
    53 }
    QAQ

    哦注明下,这是我高一上学期写的,码风清奇……

    不过总有人喜欢的。

    2.luoogu P3567,bzoj3524 couriers(权限题)

    真是的要什么权限题!洛谷提交地址

    随手记录下size就好啦,不过这题甚至不用离散化23333

     1 #include<bits/stdc++.h>
     2 #define N 500005
     3 using namespace std;
     4 int n,m,a[N],ls[25*N],rs[25*N],size[25*N],cnt=0,rt[N];
     5 void ins(int &o,int pre,int l,int r,int q){
     6     o=++cnt;int mid=(l+r)>>1;
     7     ls[o]=ls[pre];rs[o]=rs[pre];size[o]=size[pre]+1;
     8     if(l==r)return;
     9     if(q<=mid)ins(ls[o],ls[pre],l,mid,q);
    10     else ins(rs[o],rs[pre],mid+1,r,q);
    11 }
    12 int query(int x,int y,int l,int r,int q){
    13     if(l==r)return l;int mid=(l+r)>>1;
    14     int lsize=(size[ls[x]]-size[ls[y]]),rsize=(size[rs[x]]-size[rs[y]]);
    15     if(lsize>q)return query(ls[x],ls[y],l,mid,q);
    16     else if(rsize>q)return query(rs[x],rs[y],mid+1,r,q);
    17     else return 0;
    18 }
    19 inline int read(){
    20     int f=1,x=0;char ch;
    21     do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    22     do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    23     return f*x;
    24 }
    25 int main(){
    26     n=read();m=read();
    27     for(int i=1;i<=n;i++)a[i]=read();
    28     for(int i=1;i<=n;i++)ins(rt[i],rt[i-1],1,n,a[i]);
    29     while(m--){
    30         int l=read(),r=read();
    31         printf("%d
    ",query(rt[r],rt[l-1],1,n,(r-l+1)>>1));
    32     }
    33     return 0;
    34 }
    点这里

    3.mex

    啥是mex?就是SG函数的mex啊。

    之前写的莫队,后来发现主席树也很资瓷。

    注意从0开始就好。

     1 #include<bits/stdc++.h>
     2 #define N 300005
     3 #define M 6000005
     4 using namespace std;
     5 int n,q,cnt,a[N],ls[M],rs[M],rt[M],minv[M];
     6 void ins(int &x,int fa,int l,int r,int q,int val){
     7     x=++cnt;minv[x]=minv[fa];
     8     ls[x]=ls[fa];rs[x]=rs[fa];
     9     if(l==r){minv[x]=val;return;}
    10     int mid=(l+r)>>1;
    11     if(q<=mid)ins(ls[x],ls[fa],l,mid,q,val);
    12     else ins(rs[x],rs[fa],mid+1,r,q,val);
    13     minv[x]=min(minv[ls[x]],minv[rs[x]]);
    14 }
    15 int query(int x,int l,int r,int q){
    16     if(l==r)return l;
    17     int mid=(l+r)>>1;
    18     if(minv[ls[x]]>=q)return query(rs[x],mid+1,r,q);
    19     else return query(ls[x],l,mid,q);
    20 }
    21 inline int read(){
    22     int f=1,x=0;char ch;
    23     do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    24     do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    25     return f*x;
    26 }
    27 int main(){
    28     n=read();q=read();
    29     for(int i=1;i<=n;i++)a[i]=read();
    30     for(int i=1;i<=n;i++)ins(rt[i],rt[i-1],0,1000000,a[i],i);
    31     while(q--){
    32         int x=read(),y=read();
    33         printf("%d
    ",query(rt[y],0,1000000,x));
    34     }
    35     return 0;
    36 }
    点这里的都是神犇!

    4.dynamic ranking
    详见之前blog。

     1 #include<bits/stdc++.h>
     2 #define N 10005
     3 using namespace std;
     4 inline int lowbit(int x){return x&-x;}
     5 int n,m,sz,totn,totx,toty,a[N],b[N<<1],ca[N],cb[N],cc[N];
     6 int xx[N],yy[N],rt[N],size[600*N],ls[600*N],rs[600*N];
     7 void ins(int &o,int l,int r,int x,int q,int v){
     8     o=++sz;size[o]=size[x]+v;ls[o]=ls[x];rs[o]=rs[x];
     9     if(l==r)return;int mid=(l+r)>>1;
    10     if(q<=mid)ins(ls[o],l,mid,ls[x],q,v);
    11     else ins(rs[o],mid+1,r,rs[x],q,v);
    12 }
    13 int query(int l,int r,int q){
    14     if(l==r)return l;
    15     int sum=0,mid=(l+r)>>1;
    16     for(int i=1;i<=totx;i++)sum-=size[ls[xx[i]]];
    17     for(int i=1;i<=toty;i++)sum+=size[ls[yy[i]]];
    18     if(q<=sum){
    19         for(int i=1;i<=totx;i++)xx[i]=ls[xx[i]];
    20         for(int i=1;i<=toty;i++)yy[i]=ls[yy[i]];
    21         return query(l,mid,q);
    22     }
    23     else{
    24         for(int i=1;i<=totx;i++)xx[i]=rs[xx[i]];
    25         for(int i=1;i<=toty;i++)yy[i]=rs[yy[i]];
    26         return query(mid+1,r,q-sum);
    27     }
    28 }
    29 void add(int x,int v){
    30     int k=lower_bound(b+1,b+totn+1,a[x])-b;
    31     for(int i=x;i<=n;i+=lowbit(i))ins(rt[i],1,totn,rt[i],k,v);
    32 }
    33 inline int read(){
    34     int f=1,x=0;char ch;
    35     do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    36     do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    37     return f*x;
    38 }
    39 int main(){char s[20];
    40     n=read();m=read();
    41     for(int i=1;i<=n;i++)a[i]=read(),b[++totn]=a[i];
    42     for(int i=1;i<=m;i++){
    43         scanf("%s",s);ca[i]=read();cb[i]=read();
    44         if(s[0]=='Q')cc[i]=read();else b[++totn]=cb[i];
    45     }
    46     sort(b+1,b+totn+1);
    47     totn=unique(b+1,b+totn+1)-b-1;
    48     for(int i=1;i<=n;i++)add(i,1);
    49     for(int i=1;i<=m;i++){
    50         if(cc[i]){
    51             totx=toty=0;
    52             for(int j=ca[i]-1;j;j-=lowbit(j))xx[++totx]=rt[j];
    53             for(int j=cb[i];j;j-=lowbit(j))yy[++toty]=rt[j];
    54             printf("%d
    ",b[query(1,totn,cc[i])]);
    55         }
    56         else{add(ca[i],-1);a[ca[i]]=cb[i];add(ca[i],1);}
    57     }
    58 }
    带修改主席树

    5.任务查询系统
    这里是bzoj的地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3932

    按照时间随意差分,差分完上树就行。

     1 #include<bits/stdc++.h>
     2 #define N 100005
     3 using namespace std;
     4 int n,m,pre=1,totn,h[N],rt[N],cnt=0,ls[50*N],rs[50*N],size[50*N],sumv[50*N];
     5 vector<int>a[N];
     6 void ins(int &o,int pre,int l,int r,int q,int v){
     7     o=++cnt;ls[o]=ls[pre];rs[o]=rs[pre];
     8     size[o]=size[pre]+v;sumv[o]=sumv[pre]+h[q]*v;
     9     if(l==r)return;int mid=(l+r)>>1;
    10     if(q<=mid)ins(ls[o],ls[pre],l,mid,q,v);
    11     else ins(rs[o],rs[pre],mid+1,r,q,v);
    12 }
    13 int query(int o,int l,int r,int q){
    14     if(q>=size[o])return sumv[o];
    15     if(l==r)return sumv[o]/size[o]*q;
    16     int mid=(l+r)>>1,ans=query(ls[o],l,mid,q);
    17     if(q>size[ls[o]])ans+=query(rs[o],mid+1,r,q-size[ls[o]]);
    18     return ans;
    19 }
    20 inline int read(){
    21     int f=1,x=0;char ch;
    22     do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    23     do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    24     return f*x;
    25 }
    26 int main(){
    27     m=read();n=read();
    28     for(int i=1;i<=m;i++){
    29         int x=read(),y=read(),z=read();
    30         a[x].push_back(z);a[y+1].push_back(-z);
    31         h[i]=z;
    32     }
    33     sort(h+1,h+m+1);totn=unique(h+1,h+m+1)-h-1;
    34     for(int i=1;i<=n;i++){
    35         rt[i]=rt[i-1];
    36         for(int j=0;j<a[i].size();j++){
    37             int k=1;if(a[i][j]<0)k*=-1,a[i][j]*=-1;
    38             ins(rt[i],rt[i],1,totn,lower_bound(h+1,h+totn+1,a[i][j])-h,k);
    39         }
    40     }
    41     while(n--){
    42         int X=read(),A=read(),B=read(),C=read();
    43         printf("%d
    ",pre=query(rt[X],1,totn,1+((long long)A*pre+B)%C));
    44     }
    45     return 0;
    46 }
    naive

    啊呸这鬼题目,n,m怎么是反的啊!

    为了这个sb错误找半天的zcysky是不是也是sb啊……

    zzq wc-ctsc-apio-NOI Au;yql精通多项式;zyz精通女装;由乃精通数据结构;孔老师是毒奶大师;我没有学上:我们都有光明的前途。
  • 相关阅读:
    【HDU 2093】考试排名(结构体水题)
    【HDU 2037】今年暑假不AC
    【HDU 1234】开门人和关门人(水题)
    【HDU 1005】Number Sequence
    第一篇博客——ACM之路!
    深度学习全家福
    搭建 keras + tensorflow
    MSCI 成份股 清单
    SK-Learn 全家福
    创业笔记 -- 网站正式对外运营
  • 原文地址:https://www.cnblogs.com/zcysky/p/6835055.html
Copyright © 2011-2022 走看看