首页 > 代码库 > [COGS257]动态排名系统 树状数组套主席树

[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

 

题解:

如果你没有听过“树状数组套主席树”这个概念,你选择可以移步我的讲解

本题就是一个树状数组套主席树的板子题,如果用指针打的话操作时可以用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\n",query(a,b,1,MAXN,c));
93         else scanf("%d%d",&a,&b),change(a,b);
94     }
95 }

 

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