1. 程式人生 > >3196. 二逼平衡樹【線段樹套splay】

3196. 二逼平衡樹【線段樹套splay】

== ins stream ostream %d 需要 output edi afa

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 6
4 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

2
4
3
4
9

HINT

1.n和m的數據範圍:n,m<=50000

2.序列中每個數的數據範圍:[0,1e8]

3.雖然原題沒有,但事實上5操作的k可能為負數
  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #define N (3000000+100)
  5 using namespace std;
  6 
  7 int Root[N],sz,Father[N],Son[N][2];
  8 int Cnt[N],Val[N],Size[N];
  9 int n,m,a[N],Ans,maxn;
10 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();} 15 while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();} 16 return x*f; 17 } 18 19 struct Splay_Tree 20 { 21 int Get(int x) { return Son[Father[x]][1]==x; } 22 void Update(int x) { Size[x]=Size[Son[x][0]]+Size[Son[x][1]]+Cnt[x]; } 23 void New(int x) { ++sz; Size[sz]=1; Val[sz]=x; Cnt[sz]=1; } 24 void Clear(int x) { Size[x]=Father[x]=Son[x][0]=Son[x][1]=Cnt[x]=Val[x]=0; } 25 int Pre(int Root) { int now=Son[Root][0]; while (Son[now][1]) now=Son[now][1]; return now; } 26 int Next(int Root) { int now=Son[Root][1]; while (Son[now][0]) now=Son[now][0]; return now; } 27 28 void Rotate(int x) 29 { 30 int wh=Get(x),fa=Father[x],fafa=Father[fa]; 31 if (fafa) Son[fafa][Son[fafa][1]==fa]=x; 32 Father[fa]=x; Son[fa][wh]=Son[x][wh^1]; 33 if (Son[fa][wh]) Father[Son[fa][wh]]=fa; 34 Father[x]=fafa; Son[x][wh^1]=fa; 35 Update(fa); Update(x); 36 } 37 void Splay(int &Root,int x) 38 { 39 for (int fa;fa=Father[x];Rotate(x)) 40 if (Father[fa]) 41 Rotate(Get(fa)==Get(x)?fa:x); 42 Root=x; 43 } 44 int Findx(int &Root,int x) 45 { 46 int now=Root; 47 while (1) 48 if (x<=Size[Son[now][0]]) 49 now=Son[now][0]; 50 else 51 { 52 if (x<=Cnt[now]) 53 { 54 Splay(Root,now); 55 return now; 56 } 57 x-=Cnt[now]; 58 now=Son[now][1]; 59 } 60 } 61 int Find(int &Root,int x) 62 { 63 int now=Root,ans=0; 64 while (1) 65 { 66 if (!now) return ans; 67 if (x<Val[now]) 68 now=Son[now][0]; 69 else 70 { 71 ans+=Size[Son[now][0]]; 72 if (Val[now]==x) 73 { 74 Splay(Root,now); 75 return ans; 76 } 77 ans+=Cnt[now]; 78 now=Son[now][1]; 79 } 80 } 81 } 82 void Insert(int &Root,int x) 83 { 84 if (!Root) { New(x); Root=sz; return; } 85 int now=Root,fa=0; 86 while (1) 87 { 88 if (x==Val[now]) { ++Cnt[now]; Update(now); Splay(Root,now); return; } 89 fa=now; now=Son[now][x>Val[now]]; 90 if (now==0){ New(x); Father[sz]=fa; Son[fa][x>Val[fa]]=sz; Splay(Root,sz); return; } 91 } 92 } 93 void Delete(int &Root,int x) 94 { 95 Find(Root,x); 96 if (Cnt[Root]>1) { Cnt[Root]--; Update(Root); return; } 97 if (!Son[Root][0] && !Son[Root][1]) { Clear(Root); Root=0; return; } 98 if (!Son[Root][1]) { Root=Son[Root][0]; Clear(Father[Root]); Father[Root]=0; return; } 99 if (!Son[Root][0]) { Root=Son[Root][1]; Clear(Father[Root]); Father[Root]=0; return; } 100 101 int oldroot=Root,pre=Pre(Root); 102 Splay(Root,pre); 103 Son[Root][1]=Son[oldroot][1]; 104 Father[Son[oldroot][1]]=Root; 105 Clear(oldroot); 106 Update(Root); 107 } 108 }; 109 110 struct Segt_Tree 111 { 112 Splay_Tree Splay[200001]; 113 void Get_rank(int node,int l,int r,int l1,int r1,int k) 114 { 115 if (l>r1 || r<l1) return; 116 if (l1<=l && r<=r1) 117 { 118 Ans+=Splay[node].Find(Root[node],k); 119 return; 120 } 121 int mid=(l+r)>>1; 122 Get_rank(node<<1,l,mid,l1,r1,k); 123 Get_rank(node<<1|1,mid+1,r,l1,r1,k); 124 } 125 void Update(int node,int l,int r,int x,int k) 126 { 127 Splay[node].Delete(Root[node],a[x]); 128 Splay[node].Insert(Root[node],k); 129 if (l==r) return; 130 int mid=(l+r)>>1; 131 if (x<=mid) Update(node<<1,l,mid,x,k); 132 else Update(node<<1|1,mid+1,r,x,k); 133 } 134 void Pre(int node,int l,int r,int l1,int r1,int k) 135 { 136 if (l>r1 || r<l1) return; 137 if (l1<=l && r<=r1) 138 { 139 Splay[node].Insert(Root[node],k); 140 int pre=Splay[node].Pre(Root[node]); 141 Ans=max(Ans,Val[pre]); 142 Splay[node].Delete(Root[node],k); 143 return; 144 } 145 int mid=(l+r)>>1; 146 Pre(node<<1,l,mid,l1,r1,k); 147 Pre(node<<1|1,mid+1,r,l1,r1,k); 148 } 149 void Next(int node,int l,int r,int l1,int r1,int k) 150 { 151 if (l>r1 || r<l1) return; 152 if (l1<=l && r<=r1) 153 { 154 Splay[node].Insert(Root[node],k); 155 int next=Splay[node].Next(Root[node]); 156 Ans=min(Ans,next==0?0x7fffffff:Val[next]); 157 Splay[node].Delete(Root[node],k); 158 return; 159 } 160 int mid=(l+r)>>1; 161 Next(node<<1,l,mid,l1,r1,k); 162 Next(node<<1|1,mid+1,r,l1,r1,k); 163 } 164 void Ins(int node,int l,int r,int x,int k) 165 { 166 Splay[node].Insert(Root[node],k); 167 if (l==r) return; 168 int mid=(l+r)>>1; 169 if (x<=mid) Ins(node<<1,l,mid,x,k); 170 else Ins(node<<1|1,mid+1,r,x,k); 171 } 172 }T; 173 174 int main() 175 { 176 n=read(),m=read(); 177 for (int i=1; i<=n; ++i) 178 a[i]=read(),maxn=max(maxn,a[i]),T.Ins(1,1,n,i,a[i]); 179 int opt,l,r,k,pos; 180 for (int i=1; i<=m; ++i) 181 { 182 opt=read(); 183 switch(opt) 184 { 185 case 1: 186 { 187 l=read(),r=read(),k=read(); 188 Ans=0; 189 T.Get_rank(1,1,n,l,r,k); 190 printf("%d\n",Ans+1); 191 break; 192 } 193 case 2: 194 { 195 l=read(),r=read(),k=read(); 196 int L=0,R=maxn; 197 while (L<R) 198 { 199 int mid=(L+R)>>1; 200 Ans=0; 201 T.Get_rank(1,1,n,l,r,mid); 202 if (Ans<k) L=mid+1; 203 else R=mid; 204 } 205 printf("%d\n",L-1); 206 break; 207 } 208 case 3: 209 { 210 pos=read(),k=read(); 211 T.Update(1,1,n,pos,k); 212 a[pos]=k; 213 maxn=max(maxn,k); 214 break; 215 } 216 case 4: 217 { 218 l=read(),r=read(),k=read(); 219 Ans=0; 220 T.Pre(1,1,n,l,r,k); 221 printf("%d\n",Ans); 222 break; 223 } 224 case 5: 225 { 226 l=read(),r=read(),k=read(); 227 Ans=0x7fffffff; 228 T.Next(1,1,n,l,r,k); 229 printf("%d\n",Ans); 230 break; 231 } 232 } 233 } 234 }

3196. 二逼平衡樹【線段樹套splay】