Dynamic Rankings ZOJ - 2112

点击打开链接

动态主席树模板 推荐博客点击打开链接

先用原序列的n个数建立一个静态主席树 再利用树状数组维护一个动态主席树 每次查询利用静态与动态之和 而更改只改动态主席树 即在取lowbit过程中把每个遍历到的位置对应的线段树更新一条链

这里的区间查询另开了一个use数组 因为这种区间二分查询 需要静态和动态主席树的加和来决定下一步走向

虽说树状数组可以解决的问题线段树都能解决 但是在这里如果用线段树的话 本来就很高的时间空间复杂度会更加无法承受 并且代码量也会增大很多

#include <bits/stdc++.h>
using namespace std;

struct node1
{
    int tp;
    int l;
    int r;
    int k;
};

struct node2
{
    int l;
    int r;
    int val;
};

node1 order[10010];
node2 tree[2000010];
int ary[50010],pre[60010],root[50010],groot[50010],use[50010];
int n,q,len,num;

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

int build(int l,int r)
{
    int cur,m;
    cur=num++;
    tree[cur].l=0,tree[cur].r=0,tree[cur].val=0;
    if(l==r) return cur;
    m=(l+r)/2;
    tree[cur].l=build(l,m);
    tree[cur].r=build(m+1,r);
    return cur;
}

int query(int pl,int pr,int lrot,int rrot,int k,int l,int r)
{
    int i,res,m;
    if(l==r) return l;
    res=tree[tree[rrot].l].val-tree[tree[lrot].l].val;
    for(i=pr;i>=1;i-=lowbit(i)) res+=tree[tree[use[i]].l].val;
    for(i=pl;i>=1;i-=lowbit(i)) res-=tree[tree[use[i]].l].val;
    m=(l+r)/2;
    if(res>=k)
    {
        for(i=pr;i>=1;i-=lowbit(i)) use[i]=tree[use[i]].l;
        for(i=pl;i>=1;i-=lowbit(i)) use[i]=tree[use[i]].l;
        return query(pl,pr,tree[lrot].l,tree[rrot].l,k,l,m);
    }
    else
    {
        for(i=pr;i>=1;i-=lowbit(i)) use[i]=tree[use[i]].r;
        for(i=pl;i>=1;i-=lowbit(i)) use[i]=tree[use[i]].r;
        return query(pl,pr,tree[lrot].r,tree[rrot].r,k-res,m+1,r);
    }
}

int updateI(int rot,int tar,int val,int l,int r)
{
    int cur,m;
    cur=num++;
    tree[cur]=tree[rot];
    tree[cur].val+=val;
    if(l==r) return cur;
    m=(l+r)/2;
    if(tar<=m) tree[cur].l=updateI(tree[rot].l,tar,val,l,m);
    else tree[cur].r=updateI(tree[rot].r,tar,val,m+1,r);
    return cur;
}

void updateII(int pos,int val)
{
    int i,p;
    p=lower_bound(pre+1,pre+len+1,ary[pos])-pre;
    for(i=pos;i<=n;i+=lowbit(i)) groot[i]=updateI(groot[i],p,-1,1,len);
    p=lower_bound(pre+1,pre+len+1,val)-pre;
    for(i=pos;i<=n;i+=lowbit(i)) groot[i]=updateI(groot[i],p,1,1,len);
    ary[pos]=val;
}

int main()
{
    int t,i,j,p;
    char op[10];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&q);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&ary[i]);
            pre[i]=ary[i];
        }
        len=n;
        for(i=1;i<=q;i++)
        {
            scanf("%s",op);
            if(op[0]=='Q')
            {
                order[i].tp=0;
                scanf("%d%d%d",&order[i].l,&order[i].r,&order[i].k);
            }
            else
            {
                order[i].tp=1;
                scanf("%d%d",&order[i].l,&order[i].r);
                len++;
                pre[len]=order[i].r;
            }
        }
        sort(pre+1,pre+len+1);
        len=unique(pre+1,pre+len+1)-pre-1;
        num=0;
        root[0]=build(1,len);
        for(i=1;i<=n;i++)
        {
            p=lower_bound(pre+1,pre+len+1,ary[i])-pre;
            root[i]=updateI(root[i-1],p,1,1,len);
        }
        for(i=1;i<=n;i++)
        {
            groot[i]=root[0];
        }
        for(i=1;i<=q;i++)
        {
            if(order[i].tp==0)
            {
                for(j=order[i].r;j>=1;j-=lowbit(j)) use[j]=groot[j];
                for(j=order[i].l-1;j>=1;j-=lowbit(j)) use[j]=groot[j];
                p=query(order[i].l-1,order[i].r,root[order[i].l-1],root[order[i].r],order[i].k,1,len);
                printf("%d\n",pre[p]);
            }
            else
            {
                updateII(order[i].l,order[i].r);
            }
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值