• [COGS257]动态排名系统 树状数组套主席树


    257. 动态排名系统

    时间限制:5 s   内存限制:512 MB

    [问题描述]
    给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:
    1、查询A[i],A[i+1],A[i+2],...,A[j](1<=i<=j<=N)中,升序排列后排名第k的数。
    2、修改A[i]的值为j。
    所谓排名第k,指一些数按照升序排列后,第k位的数。例如序列{6,1,9,6,6},排名第3的数是6,排名第5的数是9。
    [输入格式]
    第一行包含一个整数D(0<=D<=4),表示测试数据的数目。接下来有D组测试数据,每组测试数据中,首先是两个整数N(1<=N<=50000),M(1<=M<=10000),表示序列的长度为N,有M个操作。接下来的N个不大于1,000,000,000正整数,第i个表示序列A[i]的初始值。然后的M行,每行为一个操作
    Q i j k 或者
    C i j
    分别表示查询A[i],A[i+1],A[i+2],...,A[j](1<=i<=j<=N)中,升序排列后排名第k的数,和修改A[i]的值为j。
    [输出格式]
    对于每个查询,输出一行整数,为查询的结果。测试数据之间不应有空行。
    [样例输入]
    2
    5 3
    3 2 1 4 7
    Q 1 4 3
    C 2 6
    Q 2 5 3
    5 3
    3 2 1 4 7
    Q 1 4 3
    C 2 6
    Q 2 5 3
    [样例输出]
    3
    6
    3
    6

    题解:

    (如果你没有听过“树状数组套主席树”这个概念,你选择可以移步我的讲解http://www.cnblogs.com/LadyLex/p/7275164.html

    本题就是一个树状数组套主席树的板子题,如果用指针打的话操作时可以用vector存下需要更改的几棵树,进行修改

    查询时候和普通的静态查询也是类似的,只不过是子树数据数量之和与k比较

    这些东西还是通过代码可以更好的理解……代码见下:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <vector>
     5 using namespace std;
     6 const int N=10100,MAXN=1000000000ll;
     7 int n,val[N],tp;
     8 struct node
     9 {
    10     node *ch[2];int cnt;
    11     node(){cnt=0;ch[1]=ch[0]=NULL;}
    12     inline void update(){cnt=ch[0]->cnt+ch[1]->cnt;}
    13 }*null=new node(),*root[N*2];
    14 vector<node*>v[5];
    15 inline node* newnode()
    16 {
    17     node *o=new node();
    18     o->ch[0]=o->ch[1]=null;
    19     return o;
    20 }
    21 inline int lowbit(int a){return a&-a;}
    22 inline void get_query(int id,int pos)
    23 {
    24     v[id].clear();
    25     while(pos)v[id].push_back(root[pos]),pos-=lowbit(pos);
    26 }
    27 inline void get_set(int id,int pos)
    28 {
    29     v[id].clear();
    30     while(pos<=n)v[id].push_back(root[pos]),pos+=lowbit(pos);
    31 }
    32 inline void set(vector<node*> o,int l,int r,int pos,int opt)
    33 {
    34     while(l<r)
    35     {
    36         int mi=(l+r)>>1;
    37         for(int i=0,len=o.size();i<len;i++)if(o[i]!=null)o[i]->cnt+=opt;
    38         if(pos<=mi)
    39         {
    40             r=mi;
    41             for(int i=0,len=o.size();i<len;o[i]=o[i]->ch[0],i++)
    42                 if(o[i]->ch[0]==null)o[i]->ch[0]=newnode();
    43         }
    44         else
    45         {
    46             l=mi+1;
    47             for(int i=0,len=o.size();i<len;o[i]=o[i]->ch[1],i++)
    48                 if(o[i]->ch[1]==null)o[i]->ch[1]=newnode();
    49         }
    50     }
    51     for(int i=0,len=o.size();i<len;i++)
    52     {
    53         if(o[i]==null)o[i]=newnode();
    54         o[i]->cnt+=opt;
    55     }
    56 }
    57 inline int query(int a,int b,int l,int r,int k)
    58 {
    59     get_query(1,a-1);get_query(2,b);
    60     while(l<r)
    61     {
    62         int tmp=0,mi=(l+r)>>1;
    63         for(int i=0,len=v[1].size();i<len;i++)if(v[1][i]!=null)tmp-=v[1][i]->ch[0]->cnt;
    64         for(int i=0,len=v[2].size();i<len;i++)if(v[2][i]!=null)tmp+=v[2][i]->ch[0]->cnt;
    65         if(tmp>=k)
    66         {
    67             for(int i=0,len=v[1].size();i<len;i++)v[1][i]=v[1][i]->ch[0];
    68             for(int i=0,len=v[2].size();i<len;i++)v[2][i]=v[2][i]->ch[0];
    69             r=mi;
    70         }
    71         else
    72         {
    73             for(int i=0,len=v[1].size();i<len;i++)v[1][i]=v[1][i]->ch[1];
    74             for(int i=0,len=v[2].size();i<len;i++)v[2][i]=v[2][i]->ch[1];
    75             k-=tmp,l=mi+1;
    76         }
    77     }
    78     return r;
    79 }
    80 inline void change(int a,int b)
    81     {get_set(1,a);set(v[1],1,MAXN,val[a],-1);set(v[1],1,MAXN,b,1);val[a]=b;}
    82 int main()
    83 {
    84     int m,a,b,c;char s[3];
    85     null->ch[0]=null->ch[1]=null;
    86     scanf("%d%d",&n,&m);
    87     for(int i=1;i<=n;i++)root[i]=newnode();
    88     for(int i=1;i<=n;i++)scanf("%d",&val[i]),get_set(1,i),set(v[1],1,MAXN,val[i],1);
    89     while(m--)
    90     {
    91         scanf("%s",s);
    92         if(s[0]=='Q')scanf("%d%d%d",&a,&b,&c),printf("%d
    ",query(a,b,1,MAXN,c));
    93         else scanf("%d%d",&a,&b),change(a,b);
    94     }
    95 }
  • 相关阅读:
    常用的VI/VIM命令
    那些年学过的一些算法
    huffman编码
    好用java库(一):java date/time api:jodatime
    linux启动
    ubuntu学习方式
    地址
    各种各样的软件
    jquery文件
    C变量与数据
  • 原文地址:https://www.cnblogs.com/LadyLex/p/7275540.html
Copyright © 2020-2023  润新知