zoukankan      html  css  js  c++  java
  • HYSBZ 1901 Dynamic Rankings

    题意:
    给定一个长度为n的序列,有m次操作,分别为以下两种情况:
    1.Q left right k,查询[left,right]中的第k小数
    2.C at data,将第x位的数修改为data
    题解:
    ①带修改的主席树=主席树+树状数组
    ②与POJ 2104 K-th Number类似,只不过加上了修改操作
    ③考虑每一次修改操作,实际上它只会对[at,n]的区间产生影响
    ④我们可以开一个树状数组来记录这些修改,树状数组的每一个点都是一颗线段树
    ⑤查询的时候只要将原来的查询加上树状数组上的查询即可


    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=50000+10;
    struct Tree{
            int lch,rch;
            int data;
    }a[maxn<<5];
    struct ASK{
            int op;
            int left,right,k;
            int at,data;
    }q[maxn];
    int n,m,A[maxn];
    int Map[maxn],cnt;
    int root[maxn],num;
    int C[maxn],use[maxn];
    void Init();
    void Build(int&,int,int);
    void Update(int&,int,int,int,int,int);
    int Query(int,int,int,int,int,int,int);
    int Lowbit(int);
    void Add(int,int,int);
    int GetSum(int);
    signed main(){
            // freopen("in.cpp","r",stdin);
            int t;scanf("%d",&t);
            while(t--)Init();
            return 0;
    }
    void Init(){
            num=0;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
                    scanf("%d",&A[i]),Map[++cnt]=A[i];
            char op;
            for(int i=1;i<=m;i++){
                    scanf(" %c",&op);
                    if(op=='Q')q[i].op=1,scanf("%d%d%d",&q[i].left,&q[i].right,&q[i].k);    
                    else q[i].op=0,scanf("%d%d",&q[i].at,&q[i].data),Map[++cnt]=q[i].data;
            }
            sort(Map+1,Map+1+cnt);cnt=unique(Map+1,Map+1+cnt)-Map-1;
            Build(root[0],1,cnt);
            for(int i=1;i<=n;i++){
                    int x=lower_bound(Map+1,Map+1+cnt,A[i])-Map;
                    Update(root[i],root[i-1],1,cnt,x,1);
            }
            for(int i=1;i<=n;i++)C[i]=root[0];
            for(int i=1,x;i<=m;i++){
                    if(q[i].op){
                            for(int j=q[i].left-1;j;j-=Lowbit(j))
                                    use[j]=C[j];
                            for(int j=q[i].right;j;j-=Lowbit(j))
                                    use[j]=C[j];
                            x=Query(root[q[i].left-1],root[q[i].right],q[i].left-1,q[i].right,1,cnt,q[i].k);
                            printf("%d
    ",Map[x]);
                    }
                    else{
                            x=lower_bound(Map+1,Map+1+cnt,A[q[i].at])-Map;
                            Add(q[i].at,x,-1);
                            x=lower_bound(Map+1,Map+1+cnt,q[i].data)-Map;
                            Add(q[i].at,x,1);
                            A[q[i].at]=q[i].data;
                    }
            }
    }
    void Build(int &u,int left,int right){
            u=++num;
            a[u].data=0;
            if(left==right)return;
            int mid=(left+right)>>1;
            Build(a[u].lch,left,mid);
            Build(a[u].rch,mid+1,right);
    }
    void Update(int &u,int y,int left,int right,int pos,int key){
            u=++num;
            a[u].lch=a[y].lch;a[u].rch=a[y].rch;
            a[u].data=a[y].data+key;
            if(left==right)return;
            int mid=(left+right)>>1;
            if(pos<=mid)Update(a[u].lch,a[y].lch,left,mid,pos,key);
            else Update(a[u].rch,a[y].rch,mid+1,right,pos,key);
    }
    int Query(int u,int v,int L,int R,int left,int right,int k){
            if(left==right)return left;
            int mid=(left+right)>>1;
            int data=GetSum(R)-GetSum(L)+a[a[v].lch].data-a[a[u].lch].data;
            if(data>=k){
                    for(int i=L;i;i-=Lowbit(i))
                            use[i]=a[use[i]].lch;
                    for(int i=R;i;i-=Lowbit(i))
                            use[i]=a[use[i]].lch;
                    return Query(a[u].lch,a[v].lch,L,R,left,mid,k);
            }
            else{ 
                    for(int i=L;i;i-=Lowbit(i))
                            use[i]=a[use[i]].rch;
                    for(int i=R;i;i-=Lowbit(i))
                            use[i]=a[use[i]].rch;
                    return Query(a[u].rch,a[v].rch,L,R,mid+1,right,k-data);
            }
    }
    int Lowbit(int x){
            return x&(-x);
    }
    void Add(int x,int pos,int key){
            for(int i=x;i<=n;i+=Lowbit(i))
                    Update(C[i],C[i],1,cnt,pos,key);
    }
    int GetSum(int x){
            int ans=0;
            for(int i=x;i;i-=Lowbit(i))
                    ans+=a[a[use[i]].lch].data;
            return ans;
    }

  • 相关阅读:
    windows计数器和瓶颈
    SQL Server 2005的Resource数据库
    Android学习笔记 json数据的解析
    android的消息处理机制(图+源码分析)——Looper,Handler,Message
    JS刷新验证码
    Java取得Unix的timestamp
    (转载)DBMS_SQL package 学习
    关于Java中Http下载的一些整理
    (转载)sqlserver内存释放
    关于EL表达式
  • 原文地址:https://www.cnblogs.com/holy-unicorn/p/9510321.html
Copyright © 2011-2022 走看看