BZOJ 1901: Zju2112 Dynamic Rankings | 带修改主席树

题目:

emmmm是个权限题


题解:

带修改主席树的板子题,核心思想是用树状数组维护动态前缀和的性质来支持修改

修改的时候修改类似树状数组一样进行logn个Insert

查询的时候同理,树状数组的方法取出和这个位置相关的节点,用数组保存然后计算

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 100005
#define M 6000005
using namespace std;
int n,m,a[N],lst[N],idx;
int tot,root[N],data[M],ls[M],rs[M],cur1[N],cur2[N];
int qtype[N],q1[N],q2[N],q3[N];
char s[233];
void build(int &k,int l,int r)
{
    k=++tot;
    if (l==r) return;
    int mid=l+r>>1;
    build(ls[k],l,mid),build(rs[k],mid+1,r);
}
void change(int x,int &y,int l,int r,int p,int k)
{
    data[y=++tot]=data[x]+k,ls[y]=ls[x],rs[y]=rs[x];
    if (l==r) return;
    int mid=l+r>>1;
    if (p<=mid) change(ls[x],ls[y],l,mid,p,k);
    else change(rs[x],rs[y],mid+1,r,p,k);
}

void add(int p,int num,int x)
{
    for (;p<=n;p+=p&-p) change(root[p],root[p],1,idx,num,x);
}
int query(int ql,int qr,int k)
{
    int l=1,r=idx;
    for (int p=ql;p;p-=p&-p) cur1[p]=root[p];
    for (int p=qr;p;p-=p&-p) cur2[p]=root[p]; 
    while (l<r)
    {
        int mid=l+r>>1,sum1=0,sum2=0;
        for (int p=ql;p;p-=p&-p) sum1+=data[ls[cur1[p]]];
        for (int p=qr;p;p-=p&-p) sum2+=data[ls[cur2[p]]];
        if (sum2-sum1>=k) 
        {
            for (int p=ql;p;p-=p&-p) cur1[p]=ls[cur1[p]];
            for (int p=qr;p;p-=p&-p) cur2[p]=ls[cur2[p]];
            r=mid;
        }
        else 
        {
            l=mid+1,k-=sum2-sum1;
            for (int p=ql;p;p-=p&-p) cur1[p]=rs[cur1[p]];
            for (int p=qr;p;p-=p&-p) cur2[p]=rs[cur2[p]];
        }
    }
    return lst[l];
}
int getpos(int x)
{
    return lower_bound(lst+1,lst+idx+1,x)-lst;
}
bool isQ()
{
    char c;
    while(c=getchar(),c!='Q' && c!='C');
    return c=='Q';
}
int main()
{
    scanf("%d%d",&n,&m),idx=n;
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i]),lst[i]=a[i];
    for (int i=1;i<=m;i++)
    {
        qtype[i]=isQ();
        scanf("%d%d",q1+i,q2+i);
        if (qtype[i]) scanf("%d",q3+i);
        else lst[++idx]=q2[i];
    }
    sort(lst+1,lst+1+idx);
    idx=unique(lst+1,lst+1+idx)-lst-1;
    build(root[0],1,idx);
    for (int i=1;i<=n;i++) root[i]=root[0];
    for (int i=1;i<=n;i++) add(i,getpos(a[i]),1);
    for (int i=1;i<=m;i++)
        if (qtype[i]) printf("%d\n",query(q1[i]-1,q2[i],q3[i]));
        else 
        {
            add(q1[i],getpos(a[q1[i]]),-1);
            a[q1[i]]=q2[i];
            add(q1[i],getpos(a[q1[i]]),1);
        }
    return 0;
} 

 

posted @ 2018-01-01 12:02  MSPqwq  阅读(150)  评论(0编辑  收藏  举报