可持久化线段树

题目链接:可持久化数组

可持久化数组:

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;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容

  • 在这里,所谓“可持久化”的数据结构并非指将数据存在非易失的存储器上,而是指保存了数据修改的历史信息。比如说对可持久...
    njzwj阅读 3,987评论 0 0
  • 1.把二元查找树转变成排序的双向链表 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求不...
    曲终人散Li阅读 3,242评论 0 19
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,663评论 0 33
  • B树的定义 一棵m阶的B树满足下列条件: 树中每个结点至多有m个孩子。 除根结点和叶子结点外,其它每个结点至少有m...
    文档随手记阅读 13,013评论 0 25
  • 简书? 想找个简单点的地方,写写,说说。 没有目的,不牵扯什么,想到了,就说说。
    eace89ede61d阅读 129评论 0 1