1. 程式人生 > >[COGS257]動態排名系統 樹狀數組套主席樹

[COGS257]動態排名系統 樹狀數組套主席樹

通過 for 能夠 text spa 操作 描述 nod root

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]動態排名系統 樹狀數組套主席樹