BZOJ1901 Dynamic Rankings 带修改主席树(模板)

给出一个数列,要求支持区间查询第K小和单点修改。
因为不强制在线,先将修改操作和原数列一起离散化
建树方式更改为使用树状数组维护前缀和,主席树只记录这一个位置的 size .
修改时要在 logn 个节点上同时修改
查询时同时累加 logn 个节点的 size ,每一层记录一下 logn 个节点的左右节点对应位置
最后在树上二分计算答案
时空复杂度都是 O(nlog2n)

/**************************************************************
    Problem: 1901
    User: bdzxt
    Language: C++
    Result: Accepted
    Time:380 ms
    Memory:32716 kb
****************************************************************/

#include<bits/stdc++.h>
#define LL long long 
#define clr(x,i) memset(x,i,sizeof(x))
using namespace std;
const int N=10005;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
#define lowbit(x) (x&(-x))
struct Node{
    int l,r,sz;
}t[N*265];
int n,m,a[N],rt[N*2],tot,rk[N*2],sz;
int L[33],R[33],cntl,cntr;
int qf[N],qx[N],qy[N],qz[N];
void upd(int l,int r,int &x,int y,int p,int flag)
{
    x=++tot;t[x]=t[y];t[x].sz+=flag;
    if(l==r)return;
    int mid=(l+r)>>1;
    if(p<=mid)
      upd(l,mid,t[x].l,t[y].l,p,flag);
    else
      upd(mid+1,r,t[x].r,t[y].r,p,flag);
}
int query(int l,int r,int k)
{
    if(l==r)return l;
    int suml=0,sumr=0,mid=(l+r)>>1;
    for(int i=1;i<=cntl;i++)suml+=t[t[L[i]].l].sz;
    for(int i=1;i<=cntr;i++)sumr+=t[t[R[i]].l].sz;
    if(k<=(sumr-suml)){
        for(int i=1;i<=cntl;i++)L[i]=t[L[i]].l;
        for(int i=1;i<=cntr;i++)R[i]=t[R[i]].l;
        return query(l,mid,k);
    }
    else{
        for(int i=1;i<=cntl;i++)L[i]=t[L[i]].r;
        for(int i=1;i<=cntr;i++)R[i]=t[R[i]].r;
        return query(mid+1,r,k-(sumr-suml));
    }
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++) a[i]=rk[++sz]=read();
    char op[3];int x,y,z;
    for(int i=1;i<=m;i++)
    {
        scanf("%s",op);
        qx[i]=read();qy[i]=read();
        if(op[0]=='Q') qz[i]=read();
        else rk[++sz]=qy[i],qf[i]=1;
    }
    sort(rk+1,rk+sz+1);
    sz=unique(rk+1,rk+sz+1)-rk-1;
    for(int i=1;i<=n;i++)
    {
        int v=lower_bound(rk+1,rk+sz+1,a[i])-rk;
        for(int j=i; j<=n; j+=lowbit(j))
          upd(1,sz,rt[j],rt[j],v,1);
    }
    for(int i=1;i<=m;i++)
    {
        if(qf[i]==0){
            int v=lower_bound(rk+1,rk+sz+1,qz[i])-rk;
            cntl=cntr=0;
            for(int j=qx[i]-1; j>0; j-=lowbit(j))
              L[++cntl]=rt[j];//
            for(int j=qy[i]; j>0; j-=lowbit(j))
              R[++cntr]=rt[j];//
            int ans=rk[query(1,sz,qz[i])];
            printf("%d\n",ans);
        }
        else{
            int v=lower_bound(rk+1,rk+sz+1,a[qx[i]])-rk;
            for(int j=qx[i]; j<=n; j+=lowbit(j))
              upd(1,sz,rt[j],rt[j],v,-1);
            a[qx[i]]=qy[i];
            v=lower_bound(rk+1,rk+sz+1,qy[i])-rk;
            for(int j=qx[i]; j<=n; j+=lowbit(j))
              upd(1,sz,rt[j],rt[j],v,1);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wolf_reiser/article/details/79467900