zoukankan      html  css  js  c++  java
  • 洛谷试炼场 4-17 主席树


    layout: post
    title: 洛谷试炼场 4-17 主席树
    author: "luowentaoaa"
    catalog: true
    mathjax: true
    tags:
    - 主席树
    - 数据结构
    - 洛谷


    P3834 【模板】可持久化线段树 1(主席树)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=1e6+50;
    const ll inf=0x3f3f3f3f3f3f3f3fLL;
    int n,m,cnt,root[maxn],a[maxn],x,y,k;
    struct node{int l,r,sum;}T[maxn*20];
    vector<int>v;
    int getid(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
    void update(int l,int r,int &x,int y,int pos){
        T[++cnt]=T[y],T[cnt].sum++,x=cnt;
        if(l==r)return;
        int mid=(l+r)/2;
        if(mid>=pos)update(l,mid,T[x].l,T[y].l,pos);
        else update(mid+1,r,T[x].r,T[y].r,pos);
    }
    int query(int l,int r,int x,int y,int k){
        if(l==r)return l;
        int mid=(l+r)/2;
        int sum=T[T[y].l].sum-T[T[x].l].sum;
        if(sum>=k)return query(l,mid,T[x].l,T[y].l,k);
        else return query(mid+1,r,T[x].r,T[y].r,k-sum);
    }
    template <class T>
    inline bool read(T &ret){
        char c;int sgn;if(c=getchar(),c==EOF)return 0;
        while(c!='-'&&(c<'0'||c>'9'))c=getchar();sgn=(c=='-')?-1:1;ret=(c=='-')?0:(c-'0');
        while(c=getchar(),c>='0'&&c<='9')ret=ret*10+(c-'0');ret*=sgn;return 1;
    }
    inline void out(int x){if(x>9)out(x/10);putchar(x%10+'0');}
    int main()
    {
       /* std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);*/
        read(n);read(m);
        for(int i=1;i<=n;i++)read(a[i]),v.push_back(a[i]);
        sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());
        for(int i=1;i<=n;i++)update(1,n,root[i],root[i-1],getid(a[i]));
        while(m--){
           // cin>>x>>y>>k;
           read(x);read(y);read(k);
            out(v[query(1,n,root[x-1],root[y],k)-1]);puts("");
           // cout<<v[query(1,n,root[x-1],root[y],k)-1]<<endl;
        }
        return 0;
    }
    

    P2617 Dynamic Rankings (主席树套树状数组)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=1e6+50;
    const ll inf=0x3f3f3f3f3f3f3f3fLL;
    struct node{int l,r,sum;}s[maxn*20];
    vector<int>v;
    struct quest{char op;int x,y,k;}Q[maxn];
    inline int get(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
    inline int lowbit(int x){return x&(-x);}
    int a[maxn],b[maxn],T[maxn];
    int n,m;
    int tot;
    int len;
    int temp[2][100],cnt[2];
    void update(int &now,int l,int r,int pos,int val){
        if(now==0)now=++tot;
        s[now].sum+=val;
        if(l==r)return;
        int mid=(l+r)/2;
        if(pos<=mid)update(s[now].l,l,mid,pos,val);
        else update(s[now].r,mid+1,r,pos,val);
    }
    void uptree(int x,int val){
        int pos=get(a[x]);
        for(int i=x;i<=n;i+=lowbit(i))update(T[i],1,len,pos,val);
    }
    int query(int l,int r,int k){
        if(l==r)return l;
        int x=0,mid=(l+r)/2;
        for(int i=1;i<=cnt[1];i++)x+=s[s[temp[1][i]].l].sum;
        for(int i=1;i<=cnt[0];i++)x-=s[s[temp[0][i]].l].sum;
        if(k<=x){
            for(int i=1;i<=cnt[1];i++)temp[1][i]=s[temp[1][i]].l;
            for(int i=1;i<=cnt[0];i++)temp[0][i]=s[temp[0][i]].l;
            return query(l,mid,k);
        }
        else{
            for(int i=1;i<=cnt[1];i++)temp[1][i]=s[temp[1][i]].r;
            for(int i=1;i<=cnt[0];i++)temp[0][i]=s[temp[0][i]].r;
            return query(mid+1,r,k-x);
        }
    }
    int qutree(int x,int y,int k){
        memset(temp,0,sizeof(temp));
        cnt[0]=cnt[1]=0;
        for(int i=y;i;i-=lowbit(i))temp[1][++cnt[1]]=T[i];
        for(int i=x-1;i;i-=lowbit(i))temp[0][++cnt[0]]=T[i];
        return query(1,len,k);
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        cin>>n>>m;
        for(int i=1;i<=n;i++)cin>>a[i],v.push_back(a[i]);
        for(int i=1;i<=m;i++){
            cin>>Q[i].op>>Q[i].x>>Q[i].y;
            if(Q[i].op=='Q')cin>>Q[i].k;
            else v.push_back(Q[i].y);
        }
        sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());
        len=v.size();
        for(int i=1;i<=n;i++)uptree(i,1);
        for(int i=1;i<=m;i++){
            if(Q[i].op=='Q')cout<<v[qutree(Q[i].x,Q[i].y,Q[i].k)-1]<<endl;
            else{
                uptree(Q[i].x,-1);
                a[Q[i].x]=Q[i].y;
                uptree(Q[i].x,1);
            }
        }
        return 0;
    }
    

    [P3157 CQOI2011]动态逆序对 (主席树套树状数组)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=1e6+50;
    const ll inf=0x3f3f3f3f3f3f3f3fLL;
    struct node{int l,r,sum;}T[maxn*20];
    int a[maxn],p[maxn],c[maxn],uu,pre[maxn],suf[maxn];
    int xx[100],yy[100];
    int n,m,ooo,rot[maxn];
    inline int lowbit(int x){return x&(-x);}
    void add(int x,int k){
        for(int i=x;i<=n;i+=lowbit(i))c[i]+=k;
    }
    int getsum(int x){
        int k=0;
        for(int i=x;i;i-=lowbit(i))k+=c[i];return k;
    }
    int query(int o,int l,int r,int x,int y){
        if(!o)return 0;
        if(l>=x&&r<=y)return T[o].sum;
        else{
            int mid=(l+r)/2;
            int ans=0;
            if(x<=mid)ans+=query(T[o].l,l,mid,x,y);
            if(mid<y)ans+=query(T[o].r,mid+1,r,x,y);
            return ans;
        }
    }
    int queryRange(int uu,int vv,int xx,int yy){
        int tmp=0;
        for(int i=uu-1;i;i-=lowbit(i))
            tmp-=query(rot[i],1,n,xx,yy);
        for(int i=vv;i;i-=lowbit(i))
            tmp+=query(rot[i],1,n,xx,yy);
        return tmp;
    }
    void update(int &rt,int l,int r,int x){
        if(!rt)rt=++ooo;
        T[rt].sum++;
        if(l==r)return;
        int mid=(l+r)/2;
        if(x<=mid)update(T[rt].l,l,mid,x);
        if(mid<x)update(T[rt].r,mid+1,r,x);
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        cin>>n>>m;
        ll ans=0;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            p[a[i]]=i;
            pre[i]=getsum(n)-getsum(a[i]);
            ans+=pre[i];
            add(a[i],1);
        }
        memset(c,0,sizeof(c));
        for(int i=n;i>=1;i--){
            suf[i]=getsum(a[i]-1);
            add(a[i],1);
        }
        while(m--){
            cout<<ans<<endl;
            cin>>uu;
            uu=p[uu];
            ans-=pre[uu]+suf[uu];
            ans+=queryRange(1,uu-1,a[uu]+1,n);
            ans+=queryRange(uu+1,n,1,a[uu]-1);
            for(int i=uu;i<=n;i+=lowbit(i))
                update(rot[i],1,n,a[uu]);
        }
        return 0;
    }
    
  • 相关阅读:
    53. Maximum Subarray
    64. Minimum Path Sum
    28. Implement strStr()
    26. Remove Duplicates from Sorted Array
    21. Merge Two Sorted Lists
    14. Longest Common Prefix
    7. Reverse Integer
    412. Fizz Buzz
    linux_修改域名(centos)
    linux_redis常用数据类型操作
  • 原文地址:https://www.cnblogs.com/luowentao/p/10360012.html
Copyright © 2011-2022 走看看