动态主席树 优化版

Posted 大奕哥&VANE

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态主席树 优化版相关的知识,希望对你有一定的参考价值。

和大奕哥一起学习了主席树,机房里杰哥看了之后一直说可以优化空间,题解写的太low了,所以我今天写了一个动态开点的线段树来优化一波空间,bz上试了一下,确实比网上看的题解省空间。

网上的题解是每一次都新开点,是可持久化的写法,我写的是正经的线段树动态开点。

附上代码

#include<bits/stdc++.h>
using namespace std;
const int N=10010,INF=1e9+10;
int n,m,pl,tl,mx;
int a[N<<1],num[N<<1],crt[N<<1];
char s[10];
struct tnode
{
    int lc,rc,cnt;
}t[N*120];
struct ques
{
    int l,r,k,x,d;
    bool tmp;
}q[N];
struct node
{
    int d,id;
}p[N<<1];
bool cmp(node x,node y) {return x.d<y.d;}
void merge(int x)
{
    t[x].cnt=t[t[x].lc].cnt+t[t[x].rc].cnt;
}
void update(int &rt,int p,int d,int l,int r)
{
    if(!rt) rt=++tl;
    if(l==r)
    {
        t[rt].cnt+=d;
        return;
    }
    int mid=l+r>>1;
    if(p<=mid) update(t[rt].lc,p,d,l,mid);
    else update(t[rt].rc,p,d,mid+1,r);
    merge(rt);
}
void add(int x,int p,int d)
{
    for(int i=x;i<=n;i+=i&-i) update(i,p,d,1,mx);
}
int getsum(int x)
{
    int ans=0;
    for(int i=x;i;i-=i&-i) ans+=t[t[crt[i]].lc].cnt;
    return ans;
}
int query(int lx,int rx,int k)
{
    for(int i=lx-1;i>=1;i-=(i&(-i))) crt[i]=i;
    for(int i=rx;i>=1;i-=(i&(-i))) crt[i]=i;
    int l=1,r=mx,mid,sum;
    while(l<r)
    {
        mid=(l+r)/2;
        sum=getsum(rx)-getsum(lx-1);
        if(sum>=k)
        {
            r=mid;
            for(int i=lx-1;i>=1;i-=(i&(-i))) crt[i]=t[crt[i]].lc;
            for(int i=rx;i>=1;i-=(i&(-i))) crt[i]=t[crt[i]].lc;
        }
        else
        {
            l=mid+1;
            k-=sum;
            for(int i=lx-1;i>=1;i-=(i&(-i))) crt[i]=t[crt[i]].rc;
            for(int i=rx;i>=1;i-=(i&(-i))) crt[i]=t[crt[i]].rc;
        }
    }
    return l;
}
int main()
{
    scanf("%d%d",&n,&m);
    pl=n;tl=n;
    for(int i=1;i<=n;i++) 
    {
        scanf("%d",&a[i]);
        p[i].d=a[i];p[i].id=i;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%s",s);
        if(s[0]==Q) 
        {
            q[i].tmp=0;
            scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
        }
        else
        {
            q[i].tmp=1;
            scanf("%d%d",&q[i].x,&q[i].d);
            p[++pl].d=q[i].d;p[pl].id=n+i;
        }
    }
    sort(p+1,p+1+pl,cmp);
    mx=0;p[0].d=INF;
    for(int i=1;i<=pl;i++)
    {
        if(p[i].d!=p[i-1].d) mx++,num[mx]=p[i].d;
        if(p[i].id<=n) a[p[i].id]=mx;
        else q[p[i].id-n].d=mx;
    }
    for(int i=1;i<=n;i++) 
        add(i,a[i],1);
    for(int i=1;i<=m;i++)
    {
        if(q[i].tmp==0)
            printf("%d\n",num[query(q[i].l,q[i].r,q[i].k)]);
        else
        {
            add(q[i].x,a[q[i].x],-1);
            add(q[i].x,q[i].d,1);
            a[q[i].x]=q[i].d;
        }
    }
    return 0;
}

 

以上是关于动态主席树 优化版的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3514 Codechef MARCH14 GERALD07加强版 主席树+LCT

树套树三题 题解

zoj 2112 Dynamic Rankings 带修改区间第K大 动态主席树

[CQOI2011]动态逆序对

动态 K th

noip知识点