[Base data structure] [tree cover tree] ZOJ2112 Dynamic Rankings kth_number

Source: Internet
Author: User

The number k in the dynamic query interval is small, including two operations Q x y k and C I j. The number k in the query interval x y is smaller and the number I is replaced with j.

 

The Static Interval k can be used to divide or merge trees. dynamically, only tree trees or tree trees can be used to set the Chairman tree. Tree trees and chair trees have not yet been written, here we will talk about the two methods of writing tree covers.

First, considering that the line segment tree can be used for Interval query, and the balance tree can query the ranking of a number [number smaller than or less than or equal to this number ], in this way, we can use the line segment tree to set the balance tree to query the ranking of a number in the range x y. Therefore, we can build a line segment tree by interval, each node of a line segment tree establishes a balance tree. Because the k-th small number cannot be directly queried, the ranking on the number range x y can only be queried in the form of a binary answer, in this way, the total complexity of the query is that the second answer is a logn, the line segment tree is a logn, and the Balance Tree is a logn. The total complexity is log ^ 3n. The update method is the single point update method of the Line Segment tree, for each balancing tree at the node, delete the original value first, and then add the new value. The total complexity is log ^ 2n. Spatial complexity: The line segment tree has a total of n layers and n nodes on each layer. Therefore, the total space is nlogn.

Another tree setting method can change the query complexity to log ^ 2n. However, you need to read data offline and then discretization.

First, we will consider how to use the line segment tree to query the k largest of the entire series. First, we will discretization the series and then create a line segment tree based on the Value Field, insert and maintain the number of numbers inserted in each vertex in the interval. During each query, check whether there are k numbers in the left subtree. If yes, check whether the k number in the left subtree is small, otherwise, go to the right subtree to query the k-left subtree. When the range l = r in the line segment tree, return l, which is the answer after discretization.

In the interval query, each node creates a subscript Balance Tree to query the number of Subtrees on the left> = x & <= y. If the number exceeds k, the subtree is queried on the left, otherwise, go to the right subtree for query.

This building method needs to be read offline. If you want to force online, you can build a value field into a line segment tree, and then mark it instead of updating the end each time you update it. If you need to query it, you can build a line down, however, I have never implemented this method because I don't know how to mark it.

The following two are the submissions of Two Different build methods, 0168 are built by subscript, and 2535 are built by value.

I use a line segment tree to set treap, because treap is easier to write.

Build by Subscript:

int id(int l,int r){ return l+r | l!=r; }int tree[N<<1];struct treap{ int key,wht,count,sz,ch[2]; }tp[N*20];int nodecount;void init(){ tp[0].sz=0; tp[0].wht=-INF; tp[0].key=-1; nodecount=0; }void update(int x){ tp[x].sz=tp[tp[x].ch[0]].sz+tp[x].count+tp[tp[x].ch[1]].sz; }void rotate(int &x,int t){ int y=tp[x].ch[t]; tp[x].ch[t]=tp[y].ch[!t]; tp[y].ch[!t]=x;  update(x); update(y); x=y;}void insert(int &x,int t){   if(! x)    { x=++nodecount; tp[x].key=t; tp[x].wht=rand(); tp[x].count=1;      tp[x].ch[0]=tp[x].ch[1]=0;    }else if(tp[x].key==t) tp[x].count++;    else    { int k=tp[x].key<t; insert(tp[x].ch[k],t);      if(tp[x].wht<tp[tp[x].ch[k]].wht) rotate(x,k);    }    update(x);}void erase(int &x,int t){   if(tp[x].key==t)    {   if(tp[x].count==1)        { if(! tp[x].ch[0] && ! tp[x].ch[1]){ x=0; return; }          rotate(x,tp[tp[x].ch[0]].wht<tp[tp[x].ch[1]].wht); erase(x,t);        }else tp[x].count--;    }else erase(tp[x].ch[tp[x].key<t],t);    update(x);}int select(int x,int k){   if(! x) return 0;    if(k<tp[x].key) return select(tp[x].ch[0],k);    int q=0,p=tp[tp[x].ch[0]].sz+tp[x].count;    if(k>tp[x].key) q=select(tp[x].ch[1],k);    return p+q;}int a[N],n,m,ans;void treeinsert(int l,int r,int i,int x){   insert(tree[id(l,r)],x); if(l==r) return; int m=(l+r)>>1;    if(i<=m) treeinsert(l,m,i,x); if(i>m) treeinsert(m+1,r,i,x);}void del(int l,int r,int i,int x){   erase(tree[id(l,r)],x); if(l==r) return; int m=(l+r)>>1;    if(i<=m) del(l,m,i,x); if(i>m) del(m+1,r,i,x);}void query(int l,int r,int L,int R,int x){   if(L<=l && R>=r){ ans+=select(tree[id(l,r)],x); return; }    int m=(l+r)>>1; if(L<=m) query(l,m,L,R,x); if(R>m) query(m+1,r,L,R,x);}int main(){   int tt; scanf("%d",&tt);    while (tt--)    { scanf("%d%d",&n,&m); init(); memset(tree,0,sizeof(tree));      for(int i=1;i<=n;i++){ scanf("%d",&a[i]); treeinsert(1,n,i,a[i]); }      while (m--)      { char s[5]; int x,y,c; scanf("%s",s);        if(s[0]=='C')        { scanf("%d %d",&x,&y); del(1,n,x,a[x]); a[x]=y;          treeinsert(1,n,x,a[x]);        }else        { scanf("%d %d %d",&x,&y,&c); int l=0,r=INF,mid;          while (l<r)          { ans=0; mid=(l+r)>>1; query(1,n,x,y,mid);            if(ans<c) l=mid+1; else r=mid;          }          printf("%d\n",l);        }       }    }    return 0;}

Build by value:

#define N 60010#define M 10010struct treap{    int key,wht,count,sz,ch[2];}tp[N*15];int tree[N<<1];int nodecount,root;void init(){ tp[0].sz=0; tp[0].wht=-INF; nodecount=0; root=0;}void update(int x){tp[x].sz=tp[tp[x].ch[0]].sz+tp[x].count+tp[tp[x].ch[1]].sz;}void rotate(int &x,int t){ int y=tp[x].ch[t]; tp[x].ch[t]=tp[y].ch[!t]; tp[y].ch[!t]=x;  update(x); update(y); x=y;}void insert(int &x,int t){   if(! x)    { x=++nodecount; tp[x].key=t; tp[x].wht=rand();      tp[x].count=1; tp[x].ch[0]=tp[x].ch[1]=0;    }else if(tp[x].key==t)  tp[x].count++;    else    { int k=tp[x].key<t; insert(tp[x].ch[k],t);      if(tp[x].wht<tp[tp[x].ch[k]].wht) rotate(x,k);    }    update(x);}void erase(int &x,int t){   if(tp[x].key==t)    {   if(tp[x].count==1)        {   if(! tp[x].ch[0] && ! tp[x].ch[1]) { x=0; return; }            rotate(x,tp[tp[x].ch[0]].wht<tp[tp[x].ch[1]].wht);            erase(x,t);        } else tp[x].count--;    } else erase(tp[x].ch[tp[x].key<t],t);    update(x);}int select(int x,int t){      if(! x) return 0; if(tp[x].key>t) return select(tp[x].ch[0],t);return tp[x].count+tp[tp[x].ch[0]].sz+select(tp[x].ch[1],t);}int a[N],b[N],ord[M][5],lb;int n,m,tt;int search(int x){ int l=1,r=b[0],mid; while (l<=r){ mid=(l+r)>>1;if(b[mid]==x) return mid;  if(b[mid]<x) l=mid+1;  else r=mid-1;}}void treeinsert(int l,int r,int i,int x){insert(tree[IDX(l,r)],x); if(l==r) return; int m=(l+r)>>1;if(i<=m) treeinsert(l,m,i,x); else treeinsert(m+1,r,i,x);}void treedel(int l,int r,int i,int x){erase(tree[IDX(l,r)],x); if(l==r) return; int m=(l+r)>>1;if(i<=m) treedel(l,m,i,x); else treedel(m+1,r,i,x);}int query(int l,int r,int x,int y,int k){ if(l==r) return l; int m=(l+r)>>1;  int ans=select(tree[IDX(l,m)],y)-select(tree[IDX(l,m)],x);  if(ans>=k) return query(l,m,x,y,k); return query(m+1,r,x,y,k-ans);}int main (){scanf("%d",&tt);while (tt--){scanf("%d%d",&n,&m); b[0]=1; lb=0;memset(tree,0,sizeof(tree)); init();for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[++lb]=a[i]; }for(int i=1;i<=m;i++){char s[5]; int x,y,c; scanf("%s",s);if(s[0]=='Q'){ scanf("%d %d %d",&x,&y,&c);  ord[i][1]=1; ord[i][2]=x; ord[i][3]=y; ord[i][4]=c;}else{ scanf("%d %d",&x,&y);  ord[i][1]=2; ord[i][2]=x; ord[i][3]=y; b[++lb]=y;}}sort(b+1,b+1+lb);for(int i=1;i<=lb;i++) if(b[i]!=b[b[0]]) b[++b[0]]=b[i];for(int i=1;i<=n;i++){ a[i]=search(a[i]); treeinsert(1,b[0],a[i],i); }for(int i=1;i<=m;i++){if(ord[i][1]==1)printf("%d\n",b[query(1,b[0],ord[i][2]-1,ord[i][3],ord[i][4])]);else{ treedel(1,b[0],a[ord[i][2]],ord[i][2]);  a[ord[i][2]]=search(ord[i][3]);  treeinsert(1,b[0],a[ord[i][2]],ord[i][2]);}}}return 0;}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.