You need to write a data structure (refer to the topic title) to maintain an ordered series. The following operations are required:
1. query the ranking of K in the interval
2. query the value of the row named K in the interval.
3. Modify the value of a certain bit.
4. query the precursor of K in the range (the precursor is defined as less than X and the maximum number)
5. query the successor of K within the range (defined as greater than X and the smallest number)
Question: a decision tree is a line segment tree. Each node has a Balance Tree (the Balance Tree records LS and RS, so the root node can traverse the entire tree ), without considering the space issue, ask (L, R) can be divided into multiple line segment tree intervals, and each interval has a Balance Tree to query the ranking. The operations 1 & 3-5 are very easy to implement, ranking query requires a second answer and some special skills. My practice is to obtain the possible minimum value in the second, and then take its successor. I don't know if there are any illegal operations (for example, 1 3 3 3 3 4 Xth 3). I have added some special skills and they are all details.
I have never understood the space problem before. I thought that the line segment tree has 4 * n nodes. Each node requires a balance tree with N nodes, and the space will exceed. Actually not. Each layer of a line segment tree requires a total of N line segment trees, a total of N loglayers, and the number of nodes added together is nlogn. With the modification operation, the space complexity is O (m + n) logn + 4 * n)
The time complexity is O (nlognlognlogmaxai)
This question also found a problem where I wrote a line segment tree. Alert yourself:Do not forget to deal with the boundary issue if the line segment tree is ugly! If (k> = 4 * n) return;
Another approach is the chairman tree? Faster?
#include<iostream>#include<cstdio>#include<cstdlib>#define N 50005#define NN 1600000 //(M+N)logN#define inf 1<<30#define pa pair<int,int>#define mp make_pairusing namespace std;struct seg{int l,r,rt;}st[N*4];struct treap{int ls,rs,val,key,sz;}T[NN];int n,m,num=0,a[N],ret_getrank,ret_getpre,ret_getsuc;void upd(int x){T[x].sz=T[T[x].ls].sz+T[T[x].rs].sz+1;}int merge(int a,int b){ if(a==0||b==0) return a+b; if(T[a].key<T[b].key) {T[a].rs=merge(T[a].rs,b),upd(a);return a;} else {T[b].ls=merge(a,T[b].ls),upd(b);return b;}}pa split(int a,int k){ pa tmp; if(k==0) return mp(0,a); int ls=T[a].ls,rs=T[a].rs; if(T[ls].sz==k) {T[a].ls=0;upd(a);return mp(ls,a);} if(T[ls].sz+1==k) {T[a].rs=0;upd(a);return mp(a,rs);} if(T[ls].sz>k) {tmp=split(ls,k);T[a].ls=tmp.second;upd(a);return mp(tmp.first,a);} if(T[ls].sz+1<k) {tmp=split(rs,k-T[ls].sz-1);T[a].rs=tmp.first;upd(a);return mp(a,tmp.second);}}pa rank(int k,int x){ int tmp=inf,ans=0; while(k){ if(T[k].val==x) tmp=min(tmp,ans+T[T[k].ls].sz+1),k=T[k].ls; else if(T[k].val<x) ans+=T[T[k].ls].sz+1,k=T[k].rs; else if(T[k].val>x) k=T[k].ls; } return tmp==inf?mp(ans,0):mp(tmp,1);}int pre(int k,int x){ int ans=-inf; while(k){ if(T[k].val<x) ans=max(ans,T[k].val),k=T[k].rs; else k=T[k].ls; } return ans;}int suc(int k,int x){ int ans=inf; while(k){ if(T[k].val>x) ans=min(ans,T[k].val),k=T[k].ls; else k=T[k].rs; } return ans;}void ins(int &r,int x){ //st[r].rt = root int k=rank(r,x).first; T[++num].ls=0;T[num].rs=0;T[num].sz=1; T[num].val=x;T[num].key=rand(); pa tmp=split(r,k); r=merge(tmp.first,num); r=merge(r,tmp.second);}void del(int &r,int x){ int k=rank(r,x).first; pa tmp1=split(r,k); pa tmp2=split(tmp1.first,k-1); r=merge(tmp2.first,tmp1.second);}void getrank(int k,int a,int b,int c){ if(k>=4*N) return; int l=st[k].l,r=st[k].r; if(r<a || b<l) return; if(a<=l && r<=b) {pa tmp=rank(st[k].rt,c);ret_getrank+=tmp.first-tmp.second;return;} getrank(k<<1,a,b,c);getrank(k<<1|1,a,b,c);}void getpre(int k,int a,int b,int c){ if(k>=4*N) return; int l=st[k].l,r=st[k].r; if(r<a || b<l) return; if(a<=l && r<=b) {ret_getpre=max(ret_getpre,pre(st[k].rt,c));return;} getpre(k<<1,a,b,c);getpre(k<<1|1,a,b,c);}void getsuc(int k,int a,int b,int c){ if(k>=4*N) return; int l=st[k].l,r=st[k].r; if(r<a || b<l) return; if(a<=l && r<=b) {ret_getsuc=min(ret_getsuc,suc(st[k].rt,c));return;} getsuc(k<<1,a,b,c);getsuc(k<<1|1,a,b,c);}int getxth(int a,int b,int c){ int ll=0,rr=inf; while(ll<rr){ int mid=(rr+ll)>>1; ret_getrank=0; getrank(1,a,b,mid); if(ret_getrank+1>=c) rr=mid; else ll=mid+1; } ret_getrank=0; getrank(1,a,b,ll); if(ret_getrank+1!=c) {ret_getpre=0;getpre(1,a,b,ll);return ret_getpre;} ret_getpre=0;ret_getsuc=inf; getpre(1,a,b,ll); getsuc(1,a,b,ret_getpre); return ret_getsuc;}void modify(int k,int t,int x){ if(k>=4*N) return; int l=st[k].l,r=st[k].r; if(t<l||r<t) return; if(l<=t&&t<=r) {del(st[k].rt,a[t]);ins(st[k].rt,x);} modify(k<<1,t,x);modify(k<<1|1,t,x);}void build(int k,int l,int r){ st[k].l=l;st[k].r=r; for(int i=l;i<=r;i++) ins(st[k].rt,a[i]); if(l==r) return; int mid=(l+r)>>1; build(k<<1,l,mid);build(k<<1|1,mid+1,r);}int main(){ freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); while(m--){ int opt,x,y,c;scanf("%d",&opt);ret_getrank=0;ret_getpre=0;ret_getsuc=inf; if(opt==1) scanf("%d%d%d",&x,&y,&c),getrank(1,x,y,c),printf("%d\n",ret_getrank+1); if(opt==2) scanf("%d%d%d",&x,&y,&c),printf("%d\n",getxth(x,y,c)); if(opt==3) scanf("%d%d",&x,&y),modify(1,x,y),a[x]=y; if(opt==4) {scanf("%d%d%d",&x,&y,&c);getpre(1,x,y,c);ret_getpre=ret_getpre==-inf?0:ret_getpre;printf("%d\n",ret_getpre);} if(opt==5) {scanf("%d%d%d",&x,&y,&c);getsuc(1,x,y,c);ret_getsuc=ret_getsuc==inf?0:ret_getsuc;printf("%d\n",ret_getsuc);} } return 0;}
Bzoj3196 Balance Tree Line Segment Decision Tree