可持久化线段树

题目链接:可持久化数组

可持久化数组:

struct PersistentArray
{
    const static int __=1e6+5;

    #define ls(x) t[x].lson
    #define rs(x) t[x].rson

    struct node
    {
        int val,lson,rson;
        void clear()
        {
            val=lson=rson=0;
        }
    }t[__*20];

    int *a,n,idx;
    int root[__*20],rt;

    PersistentArray() {clear();}

    void build(int _a[],int _n)
    {
        a=_a,n=_n;
        root[0]=++idx;
        t[idx].clear();
        build(root[0],1,n);
    }

    void build(int x,int tl,int tr)
    {
        if(tl==tr)
        {
            t[x].val=a[tl];
            return;
        }
        int tm=(tl+tr)>>1;
        t[ls(x)=++idx].clear();
        build(ls(x),tl,tm);
        t[rs(x)=++idx].clear();
        build(rs(x),tm+1,tr);
    }

    //基于版本y, x位置的值改为v, 返回新链的根
    int set(int y,int x,int v)
    {
        y=root[y];
        t[root[++rt]=++idx].clear();
        _set(y,root[rt],x,v);
        return root[rt];
    }

    void _set(int pn,int nn,int pos,int val)
    {
        int tl=1,tr=n;
        while(tl!=tr)
        {
            int tm=(tl+tr)>>1;
            if(pos<=tm)
            {
                rs(nn)=rs(pn),ls(nn)=++idx;
                pn=ls(pn),nn=idx,tr=tm;
            }
            else
            {
                ls(nn)=ls(pn),rs(nn)=++idx;
                pn=rs(pn),nn=idx,tl=tm+1;
            }
        }
        t[idx].val=val;
    }

    //版本y中位置pos的元素
    int get(int y,int pos)
    {
        root[++rt]=root[y];
        int tl=1,tr=n,x=root[y];
        while(tl!=tr)
        {
            int tm=(tl+tr)>>1;
            if(pos<=tm)
                x=ls(x),tr=tm;
            else
                x=rs(x),tl=tm+1;
        }
        return t[x].val;
    }

    void clear() {idx=rt=0;}
}pa;

题目链接:Kth number

静态主席树:

struct Discretization
{
    const static int __=1e5+5;

    ll a[__],b[__];int idx;

    Discretization() {clear();}

    ll operator[](int x){return b[x];}

    void push_back(ll x){a[++idx]=x;}

    void build()
    {
        sort(a+1,a+1+idx);
        idx=unique(a+1,a+1+idx)-a-1;
    }

    int get(ll x)
    {
        int y=lower_bound(a+1,a+1+idx,x)-a;
        b[y]=x;
        return y;
    }

    void clear() {idx=0;}
}D;

//权值主席树
struct PersistentSegmentTree
{
    #define ls(x) t[x].lson
    #define rs(x) t[x].rson

    const static int __=1e5+5;
    const static int nlogn=__*((int)log2(__)+2);

    struct node
    {
        int lson,rson,val;
        void clear()
        {
            val=lson=rson=0;
        }
    }t[nlogn];

    int n,idx,pos,val;
    int root[__],rt;

    PersistentSegmentTree() {t[0].clear();clear();}

    void build(int _n)
    {
        clear();n=_n;D.clear();
        for(int i=1;i<=n;++i)
            D.pb(a[i]);
        D.build();
        for(int i=1;i<=n;++i)
            add(D.get(a[i]),1);
    }

    void pushup(int x)
    {
        t[x].val=t[ls(x)].val+t[rs(x)].val;
    }

    //位置x的值+v
    void add(int x,int v)
    {
        pos=x,val=v;
        root[++rt]=++idx;
        t[idx].clear();
        _add(root[rt-1],root[rt],1,n);
    }

    //pn:前一个节点  nn:当前节点
    void _add(int pn,int nn,int tl,int tr)
    {
        int tm=(tl+tr)>>1;
        if(tl==pos && pos==tr)
        {
            t[nn].val=t[pn].val+val;
            return;
        }
        if(pos<=tm)
        {
            rs(nn)=rs(pn),ls(nn)=++idx;
            t[idx].clear();
            _add(ls(pn),idx,tl,tm);
        }
        else
        {
            ls(nn)=ls(pn),rs(nn)=++idx;
            t[idx].clear();
            _add(rs(pn),idx,tm+1,tr);
        }
        pushup(nn);
    }

    //区间[l,r]第k大的值
    ll kth(int l,int r,int k)
    {
        return D[_kth(root[l-1],root[r],1,n,k)];
    }

    int _kth(int ln,int rn,int tl,int tr,int k)
    {
        if(tl==tr)return tl;
        int lv=t[ls(rn)].val-t[ls(ln)].val;
        int tm=(tl+tr)>>1;
        if(k<=lv)
            return _kth(ls(ln),ls(rn),tl,tm,k);
        return _kth(rs(ln),rs(rn),tm+1,tr,k-lv);
    }

    void clear() {idx=rt=0;}
}pst;

题目链接:Dynamic Rankings

主席树(单点修改):

int lowbit(int x)
{
    return x&(-x);
}

struct node
{
    int lson,rson,val;
    node():val(0),lson(0),rson(0) {}
} tree[1400000];

int a[50005],lisan[60005],que[10005][4];
int ys[60005],root[50005],l_node[30],r_node[30];
int idx;

void build(int pre,int id,int tl,int tr,int wz,int val)
{
    tree[id].val=tree[pre].val+val;
    if(tl==wz && wz==tr)
        return;
    int tm=(tl+tr)>>1;
    if(wz<=tm)
    {
        tree[id].rson=tree[pre].rson;
        tree[id].lson=++idx;
        build(tree[pre].lson,idx,tl,tm,wz,val);
    }
    else
    {
        tree[id].lson=tree[pre].lson;
        tree[id].rson=++idx;
        build(tree[pre].rson,idx,tm+1,tr,wz,val);
    }
}

int query(int l_num,int r_num,int tl,int tr,int l_now,int r_now,int k)
{
    if(tl==tr)return tl;
    int sum=tree[tree[r_now].lson].val-tree[tree[l_now].lson].val;
    for(int i=1; i<=l_num; i++)
        sum-=tree[tree[l_node[i]].lson].val;
    for(int i=1; i<=r_num; i++)
        sum+=tree[tree[r_node[i]].lson].val;
    int tm=(tl+tr)>>1;
    if(k<=sum)
    {
        for(int i=1; i<=l_num; i++)
            l_node[i]=tree[l_node[i]].lson;
        for(int i=1; i<=r_num; i++)
            r_node[i]=tree[r_node[i]].lson;
        return query(l_num,r_num,tl,tm,tree[l_now].lson,tree[r_now].lson,k);
    }
    else
    {
        for(int i=1; i<=l_num; i++)
            l_node[i]=tree[l_node[i]].rson;
        for(int i=1; i<=r_num; i++)
            r_node[i]=tree[r_node[i]].rson;
        return query(l_num,r_num,tm+1,tr,tree[l_now].rson,tree[r_now].rson,k-sum);
    }
}

void update(int num,int tl,int tr,int wz,int val)
{
    if(tl==wz && wz==tr)
    {
        for(int i=1; i<=num; i++)
            tree[l_node[i]].val+=val;
        return;
    }
    int tm=(tl+tr)>>1;
    if(wz<=tm)
    {
        for(int i=1; i<=num; i++)
        {
            tree[l_node[i]].val+=val;
            if(!tree[l_node[i]].lson)
                tree[l_node[i]].lson=++idx;
            l_node[i]=tree[l_node[i]].lson;
        }
        update(num,tl,tm,wz,val);
    }
    else
    {
        for(int i=1; i<=num; i++)
        {
            tree[l_node[i]].val+=val;
            if(!tree[l_node[i]].rson)
                tree[l_node[i]].rson=++idx;
            l_node[i]=tree[l_node[i]].rson;
        }
        update(num,tm+1,tr,wz,val);
    }
}

void init(void)
{
    memset(a,0,sizeof(a));
    memset(tree,0,sizeof(tree));
    memset(que,0,sizeof(que));
    memset(ys,0,sizeof(ys));
    memset(root,0,sizeof(root));
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        int n,q,k=0;
        scanf("%d%d",&n,&q);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            lisan[k++]=a[i];
        }
        for(int i=1; i<=q; i++)
        {
            char op[2];
            scanf("%s",op);
            if(op[0]=='Q')
            {
                que[i][0]=0;
                for(int j=1; j<=3; j++)
                    scanf("%d",&que[i][j]);
            }
            if(op[0]=='C')
            {
                que[i][0]=1;
                for(int j=1; j<=2; j++)
                    scanf("%d",&que[i][j]);
                lisan[k++]=que[i][2];
            }
        }
        idx=n;
        sort(lisan,lisan+k);
        int len=unique(lisan,lisan+k)-lisan;
        for(int i=1; i<=n; i++)
        {
            int x=lower_bound(lisan,lisan+len,a[i])-lisan+1;
            ys[x]=a[i];
            build(i-1,i,1,len,x,1);
        }
        for(int i=1; i<=q; i++)
        {
            if(que[i][0]==0)
            {
                int l_num=0,r_num=0;
                for(int j=que[i][1]-1; j; j-=lowbit(j))
                {
                    l_node[++l_num]=root[j];
                }
                for(int j=que[i][2]; j; j-=lowbit(j))
                {
                    r_node[++r_num]=root[j];
                }
                int res=query(l_num,r_num,1,len,que[i][1]-1,que[i][2],que[i][3]);
                printf("%d\n",ys[res]);
            }
            if(que[i][0]==1)
            {
                int x=lower_bound(lisan,lisan+len,a[que[i][1]])-lisan+1;
                int num=0;
                for(int j=que[i][1]; j<=n; j+=lowbit(j))
                {
                    if(!root[j])root[j]=++idx;
                    l_node[++num]=root[j];
                }
                update(num,1,len,x,-1);
                a[que[i][1]]=que[i][2];
                num=0;
                for(int j=que[i][1]; j<=n; j+=lowbit(j))
                {
                    l_node[++num]=root[j];
                }
                x=lower_bound(lisan,lisan+len,que[i][2])-lisan+1;
                ys[x]=que[i][2];
                update(num,1,len,x,1);
            }
        }
    }
    return 0;
}

题目链接:动态逆序对

主席树(单点修改):

ll nixudui=0;

void guibing(int st,int mid,int ed,int a[],int t[])
{
    int x=st,y=mid+1,k=st,num=mid-st+1;
    while(x<=mid&&y<=ed)
        if(a[x]<=a[y])
            t[k++]=a[x++],num--;
        else
            t[k++]=a[y++],nixudui+=num;
    while(x<=mid)t[k++]=a[x++];
    while(y<=ed)t[k++]=a[y++];
    for(int i=st; i<=ed; i++)
        a[i]=t[i];
}

void merge_sort(int st,int ed,int a[],int t[])
{
    int mid=(st+ed)>>1;
    if(st!=mid)merge_sort(st,mid,a,t);
    if(mid+1!=ed)merge_sort(mid+1,ed,a,t);
    guibing(st,mid,ed,a,t);
}

int lowbit(int x)
{
    return x&(-x);
}

struct node
{
    int lson,rson,val;
    node():val(0),lson(0),rson(0) {}
} tree[7000000];

int a[100005],root[100005],wz[100005],t[100005];
int l_node[55],r_node[55];
int idx;

void build(int pre,int id,int tl,int tr,int wz,int val)
{
    tree[id].val=tree[pre].val+val;
    if(tl==wz && wz==tr)
        return;
    int tm=(tl+tr)>>1;
    if(wz<=tm)
    {
        tree[id].rson=tree[pre].rson;
        tree[id].lson=++idx;
        build(tree[pre].lson,idx,tl,tm,wz,val);
    }
    else
    {
        tree[id].lson=tree[pre].lson;
        tree[id].rson=++idx;
        build(tree[pre].rson,idx,tm+1,tr,wz,val);
    }
}

int query_max(int l_num,int r_num,int tl,int tr,int id,int x)
{
    if(tl==tr)return 0;
    int tm=(tl+tr)>>1,sum=0;
    if(x<=tm)
    {
        sum+=tree[tree[id].rson].val;
        for(int i=1; i<=l_num; i++)
        {
            sum-=tree[tree[l_node[i]].rson].val;
            l_node[i]=tree[l_node[i]].lson;
        }
        for(int i=1; i<=r_num; i++)
        {
            sum+=tree[tree[r_node[i]].rson].val;
            r_node[i]=tree[r_node[i]].lson;
        }
        return sum+query_max(l_num,r_num,tl,tm,tree[id].lson,x);
    }
    else
    {
        for(int i=1; i<=l_num; i++)
            l_node[i]=tree[l_node[i]].rson;
        for(int i=1; i<=r_num; i++)
            r_node[i]=tree[r_node[i]].rson;
        return query_max(l_num,r_num,tm+1,tr,tree[id].rson,x);
    }
}

int query_min(int l_num,int r_num,int tl,int tr,int pre,int id,int x)
{
    if(tl==tr)return 0;
    int tm=(tl+tr)>>1,sum=0;
    if(x<=tm)
    {
        for(int i=1; i<=l_num; i++)
            l_node[i]=tree[l_node[i]].lson;
        for(int i=1; i<=r_num; i++)
            r_node[i]=tree[r_node[i]].lson;
        return query_min(l_num,r_num,tl,tm,tree[pre].lson,tree[id].lson,x);
    }
    else
    {
        sum+=tree[tree[id].lson].val-tree[tree[pre].lson].val;
        for(int i=1; i<=l_num; i++)
        {
            sum-=tree[tree[l_node[i]].lson].val;
            l_node[i]=tree[l_node[i]].rson;
        }
        for(int i=1; i<=r_num; i++)
        {
            sum+=tree[tree[r_node[i]].lson].val;
            r_node[i]=tree[r_node[i]].rson;
        }
        return sum+query_min(l_num,r_num,tm+1,tr,tree[pre].rson,tree[id].rson,x);
    }
}

void update(int num,int tl,int tr,int wz,int val)
{
    if(tl==wz && wz==tr)
    {
        for(int i=1; i<=num; i++)
            tree[l_node[i]].val+=val;
        return;
    }
    int tm=(tl+tr)>>1;
    if(wz<=tm)
    {
        for(int i=1; i<=num; i++)
        {
            tree[l_node[i]].val+=val;
            if(!tree[l_node[i]].lson)
                tree[l_node[i]].lson=++idx;
            l_node[i]=tree[l_node[i]].lson;
        }
        update(num,tl,tm,wz,val);
    }
    else
    {
        for(int i=1; i<=num; i++)
        {
            tree[l_node[i]].val+=val;
            if(!tree[l_node[i]].rson)
                tree[l_node[i]].rson=++idx;
            l_node[i]=tree[l_node[i]].rson;
        }
        update(num,tm+1,tr,wz,val);
    }
}

int main()
{
    int n,q,x;
    scanf("%d%d",&n,&q);
    idx=n;
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        wz[a[i]]=i;
        build(i-1,i,1,n,a[i],1);
    }
    merge_sort(1,n,a,t);
    printf("%lld\n",nixudui);
    int l_num=0,r_num=0,num=0;
    while(q--)
    {
        scanf("%d",&x);
        l_num=0,r_num=0;
        for(int j=wz[x]; j; j-=lowbit(j))
            r_node[++r_num]=root[j];
        int left_max=query_max(l_num,r_num,1,n,wz[x],x);
        l_num=0,r_num=0;
        for(int j=wz[x]-1; j; j-=lowbit(j))
            l_node[++l_num]=root[j];
        for(int j=n; j; j-=lowbit(j))
            r_node[++r_num]=root[j];
        int right_min=query_min(l_num,r_num,1,n,wz[x]-1,n,x);
        nixudui-=left_max+right_min;
        if(q)printf("%lld\n",nixudui);
        num=0;
        for(int j=wz[x]; j<=n; j+=lowbit(j))
        {
            if(!root[j])root[j]=++idx;
            l_node[++num]=root[j];
        }
        update(num,1,n,x,-1);
    }
    return 0;
}

你可能感兴趣的:(可持久化线段树)