【BZOJ3196】Tyvj 1730 二逼平衡树
生活随笔
收集整理的這篇文章主要介紹了
【BZOJ3196】Tyvj 1730 二逼平衡树
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Description
您需要寫一種數據結構(可參考題目標題),來維護一個有序數列,其中需要提供以下操作:
1.查詢k在區間內的排名
2.查詢區間內排名為k的值
3.修改某一位值上的數值
4.查詢k在區間內的前驅(前驅定義為小于x,且最大的數)
5.查詢k在區間內的后繼(后繼定義為大于x,且最小的數)
Input
第一行兩個數 n,m 表示長度為n的有序序列和m個操作
第二行有n個數,表示有序序列
下面有m行,opt表示操作標號
若opt=1 則為操作1,之后有三個數l,r,k 表示查詢k在區間[l,r]的排名
若opt=2 則為操作2,之后有三個數l,r,k 表示查詢區間[l,r]內排名為k的數
若opt=3 則為操作3,之后有兩個數pos,k 表示將pos位置的數修改為k
若opt=4 則為操作4,之后有三個數l,r,k 表示查詢區間[l,r]內k的前驅
若opt=5 則為操作5,之后有三個數l,r,k 表示查詢區間[l,r]內k的后繼
Output
對于操作1,2,4,5各輸出一行,表示查詢結果
Sample Input
9 64 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5
Sample Output
24
3
4
9
HINT
?
1.n和m的數據范圍:n,m<=50000
2.序列中每個數的數據范圍:[0,1e8]
3.雖然原題沒有,但事實上5操作的k可能為負數 題解 樹套樹,調了好久,至今都不是很清楚為什么刪除節點的時候不能直接減一而必須先....說不清楚了,在代碼里體現吧 1 #include<cstdio> 2 #include<cstdlib> 3 #include<iostream> 4 using namespace std; 5 const int inf=100000000,N=3000001,M=200001; 6 int num[N],rnd[N],size[N],ls[N],rs[N],root[M],w[N],a[M]; 7 int sz,n,m,opt,l,r; 8 void updata(int k){size[k]=size[ls[k]]+size[rs[k]]+w[k];} 9 void rturn(int &k){int t=ls[k];ls[k]=rs[t];rs[t]=k;size[t]=size[k];updata(k);k=t;} 10 void lturn(int &k){int t=rs[k];rs[k]=ls[t];ls[t]=k;size[t]=size[k];updata(k);k=t;} 11 void insert(int &k,int x){ 12 if (!k){ 13 k=++sz;num[k]=x;rnd[k]=rand();size[k]=w[k]=1;return; 14 } 15 size[k]++; 16 if (x==num[k]) {w[k]++;return;} 17 if (x<num[k]) {insert(ls[k],x);if (rnd[ls[k]]<rnd[k]) rturn(k);} 18 if (x>num[k]) {insert(rs[k],x);if (rnd[rs[k]]<rnd[k]) lturn(k);} 19 } 20 21 void del(int &k,int x){ 22 if (!k) return; 23 if (num[k]==x){ 24 if (w[k]>1){w[k]--;size[k]--;return;}//就是這里,不知道為什么不是在前面直接size[k]-- 25 if(ls[k]*rs[k]==0){k=ls[k]+rs[k]; return;} 26 if (rnd[ls[k]]<rnd[rs[k]])rturn(k),del(k,x); 27 else lturn(k),del(k,x); 28 } 29 else if (num[k]>x) del(ls[k],x),size[k]--;else del(rs[k],x),size[k]--; 30 } 31 32 void change(int pos,int x){ 33 int k=1,l=1,r=n,mid=(l+r)>>1; 34 while (l!=r){ 35 mid=(l+r)>>1; 36 del(root[k],a[pos]); 37 insert(root[k],x); 38 if (mid>=pos)k=k<<1,r=mid; 39 else k=k<<1|1,l=mid+1; 40 } 41 mid=(l+r)>>1; 42 del(root[k],a[pos]); 43 insert(root[k],x); 44 } 45 46 int solve_rank(int k,int x){ 47 if (!k) return 0; 48 int l=ls[k],r=rs[k]; 49 if (num[k]==x) return size[l]; 50 else if (num[k]>x) return solve_rank(l,x); 51 else return solve_rank(r,x)+size[l]+w[k]; 52 } 53 54 int get_rank(int k,int l,int r,int L,int R,int x){ 55 if (l==L&&r==R) return (solve_rank(root[k],x)); 56 int mid=(l+r)>>1; 57 if (R<=mid) return get_rank(k<<1,l,mid,L,R,x); 58 else if (L>mid) return get_rank(k<<1|1,mid+1,r,L,R,x); 59 else return get_rank(k<<1,l,mid,L,mid,x)+get_rank(k<<1|1,mid+1,r,mid+1,R,x); 60 } 61 62 void build(int x,int y){ 63 int l=1,r=n,k=1,mid=(l+r)>>1; 64 while(l!=r){ 65 insert(root[k],y); 66 if (mid>=x) r=mid,mid=(l+r)>>1,k=k<<1; 67 else l=mid+1,mid=(l+r)>>1,k=k<<1|1; 68 } 69 insert(root[k],y); 70 } 71 72 int get_num(int x,int y,int z){ 73 int l=1,r=inf,ans; 74 while (l<=r){ 75 int mid=(l+r)>>1; 76 int tmp=get_rank(1,1,n,x,y,mid); 77 if (tmp<=z) ans=mid,l=mid+1;//因為有重復的數字,tmp偏小 78 else r=mid-1; 79 } 80 return ans; 81 } 82 83 int solve_pre(int k,int x){ 84 int l=ls[k],r=rs[k]; 85 if (!k) return 0; 86 if (num[k]<x) return max(num[k],solve_pre(r,x));//這里不要順手打上= 87 else return solve_pre(l,x); 88 } 89 90 int get_pre(int k,int l,int r,int L,int R,int x){ 91 if (l==L&&r==R) return (solve_pre(root[k],x)); 92 int mid=(l+r)>>1; 93 if (R<=mid) return get_pre(k<<1,l,mid,L,R,x); 94 else if (L>mid) return get_pre(k<<1|1,mid+1,r,L,R,x); 95 else return max(get_pre(k<<1,l,mid,L,mid,x),get_pre(k<<1|1,mid+1,r,mid+1,R,x)); 96 } 97 98 int solve_after(int k,int x){ 99 int l=ls[k],r=rs[k]; 100 if (!k) return inf; 101 if (num[k]>x) return min(num[k],solve_after(l,x));//這里不要順手打上=*2 102 else return solve_after(r,x); 103 } 104 105 int get_after(int k,int l,int r,int L,int R,int x){ 106 if (l==L&&r==R) return (solve_after(root[k],x)); 107 int mid=(l+r)>>1; 108 if (R<=mid) return get_after(k<<1,l,mid,L,R,x); 109 else if (L>mid) return get_after(k<<1|1,mid+1,r,L,R,x); 110 else return min(get_after(k<<1|1,mid+1,r,mid+1,R,x),get_after(k<<1,l,mid,L,mid,x)); 111 } 112 113 int main(){ 114 freopen("sj.txt","r",stdin); 115 freopen("me.txt","w",stdout); 116 int k; 117 scanf("%d%d",&n,&m); 118 for (int i=1;i<=n;i++){scanf("%d",&a[i]);build(i,a[i]);} 119 for (int i=1;i<=m;i++){ 120 scanf("%d%d%d",&opt,&l,&r); 121 if (opt!=3)scanf("%d",&k); 122 switch(opt){ 123 case 1:printf("%d\n",get_rank(1,1,n,l,r,k)+1);break; 124 case 2:printf("%d\n",get_num(l,r,k-1));break; 125 case 3:change(l,r);a[l]=r;break; 126 case 4:printf("%d\n",get_pre(1,1,n,l,r,k));break; 127 case 5:printf("%d\n",get_after(1,1,n,l,r,k));break; 128 } 129 } 130 }
?
轉載于:https://www.cnblogs.com/wuminyan/p/5152475.html
總結
以上是生活随笔為你收集整理的【BZOJ3196】Tyvj 1730 二逼平衡树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高数之差分方程---定义
- 下一篇: Unity3D为何能跨平台?聊聊CIL(