bzoj3196: Tyvj 1730 二逼平衡树 树套树

Posted weeping

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3196: Tyvj 1730 二逼平衡树 树套树相关的知识,希望对你有一定的参考价值。

地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3196

题目:

3196: Tyvj 1730 二逼平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 4320  Solved: 1662
[Submit][Status][Discuss]

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可能为负数
 
思路:
  第一次写树套树,以前一直觉得树套树是很可怕的东西,写了后发现思想很简单
  就是。。。。代码好长!debug麻烦!
  写了两小时,debug三小时。。
  不过1A了,美滋滋!
  代码跑了快九秒,好气哦,一定是姿势不对
  1 /**************************************************************
  2     Problem: 3196
  3     User: weeping
  4     Language: C++
  5     Result: Accepted
  6     Time:8668 ms
  7     Memory:83520 kb
  8 ****************************************************************/
  9  
 10 #include <bits/stdc++.h>
 11  
 12 using namespace std;
 13  
 14 #define lc ch[x][0]
 15 #define rc ch[x][1]
 16 #define pr fa[x]
 17  
 18 inline int read()
 19 {
 20     int a=0,f=1; char c=getchar();
 21     while (c<0||c>9) {if (c==-) f=-1; c=getchar();}
 22     while (c>=0&&c<=9) {a=a*10+c-0; c=getchar();}
 23     return a*f;
 24 }
 25  
 26 const int N = 5e4+7;
 27 const int M = 3e6;
 28  
 29 int n, m, ans, val[N];
 30 int tot, rt[M], ch[M][2], fa[M], key[M], sz[M], cnt[M];
 31  
 32 inline int wh(int x) { return ch[pr][1] == x;}
 33  
 34 inline void init(int x,int ls,int ky)
 35 {
 36     lc=rc=0,sz[x]=cnt[x]=1,key[x]=ky,pr=ls;
 37 }
 38 inline void push_up(int x)
 39 {
 40     sz[x]=sz[lc]+sz[rc]+cnt[x];
 41 }
 42 void rotate(int x)
 43 {
 44     int f = fa[x], gf = fa[f], t1 = wh(x);
 45     if( gf ) ch[gf][wh(f)] = x;
 46     fa[x] = gf, ch[f][t1] = ch[x][1^t1], fa[ch[f][t1]] = f;
 47     ch[x][t1^1] = f, fa[f] = x;
 48     push_up( f ), push_up( x );
 49 }
 50 void splay(int o,int x,int tar)
 51 {
 52     for(;pr!=tar;rotate(x))
 53     if(fa[pr]!=tar)   rotate(wh(x)==wh(pr)?pr:x);
 54     if(!tar)    rt[o]=x;
 55 }
 56 //void debug(int x)
 57 //{
 58 //    if(!x) return;
 59 //    if(lc) debug(lc);
 60 //    for(int i=1;i<=cnt[x];i++)
 61 //        printf("%d ",key[x]);
 62 //    if(rc) debug(rc);
 63 //}
 64 void insert(int o,int ky)
 65 {
 66     int x=rt[o],ls=rt[o];
 67     while(x)
 68     {
 69         if(key[x]==ky)
 70         {
 71             sz[x]++,cnt[x]++,splay(o,x,0);return;
 72         }
 73         ls=x,x=ch[x][ky>key[x]];
 74     }
 75     init(++tot,ls,ky);
 76     if(!rt[o]) { rt[o]=tot; return ;}
 77     x=ls, ch[x][ky>key[x]]=tot;
 78     splay(o,tot,0);
 79 }
 80 int find(int o,int ky)
 81 {
 82     int x=rt[o];
 83     //debug(rt[o]);printf("\n");
 84     while(x)
 85     {
 86         if(key[x]==ky)  break;
 87         x=ch[x][ky>key[x]];
 88     }
 89     if(x)   splay(o,x,0);
 90     else x=-1;
 91     return x;
 92 }
 93 void merge(int o,int x,int y)
 94 {
 95     if(!x){rt[o]=y;return;}
 96     if(!y)  {rt[o]=x;return;}
 97     while(rc)   x=rc;
 98     splay(o,x,0);
 99     rc=y,fa[y]=x;
100     push_up(x);
101 }
102 void del(int o,int ky)
103 {
104     if(!rt[o]) return;
105     int x=find(o,ky);
106     if(cnt[x]>1)    {cnt[x]--,sz[x]--;return;}
107     int tl=lc,tr=rc;
108     fa[tl]=fa[tr]=cnt[x]=sz[x]=lc=rc=0;
109     if(sz[x]==1)    {rt[o]=0;return;}
110     merge(o,tl,tr);
111 }
112 void getpre(int x,int ky)
113 {
114     if(!x)return;
115     if(key[x]<ky)  ans=max(ans,key[x]),getpre(rc,ky);
116     else getpre(lc,ky);
117 }
118 void getnext(int x,int ky)
119 {
120     if(!x) return;
121     if(key[x]>ky) ans=min(ans,key[x]),getnext(lc,ky);
122     else getnext(rc,ky);
123 }
124 int getsz(int o,int ky)
125 {
126     int x=rt[o],ret=0;
127     while(x)
128     {
129         if(key[x]==ky)  return ret+sz[lc];
130         if(key[x]<ky)   ret+=sz[lc]+cnt[x],x=rc;
131         else    x=lc;
132     }
133     return ret;
134 }
135  
136 void update(int o,int l,int r,int pos,int x,int op=0)
137 {
138     if(op)  del(o,val[pos]);
139     insert(o,x);
140     //debug(rt[o]);printf("\n");
141     if(l==r) return ;
142     int mid=l+r>>1;
143     if(pos<=mid)    update(o<<1,l,mid,pos,x,op);
144     else    update(o<<1|1,mid+1,r,pos,x,op);
145 }
146 int get_rank(int o,int l,int r,int nl,int nr,int ky)
147 {
148     //debug(rt[o]);printf("\n");
149     if(nl==l&&r==nr)    return getsz(o,ky);
150     int mid=l+r>>1;
151     if(nr<=mid) return get_rank(o<<1,l,mid,nl,nr,ky);
152     else if(nl>mid) return get_rank(o<<1|1,mid+1,r,nl,nr,ky);
153     return get_rank(o<<1,l,mid,nl,mid,ky)+get_rank(o<<1|1,mid+1,r,mid+1,nr,ky);
154 }
155 void get_pre(int o,int l,int r,int nl,int nr,int ky)
156 {
157     if(nl==l&&r==nr)    return getpre(rt[o],ky);
158     int mid=l+r>>1;
159     if(nr<=mid) return get_pre(o<<1,l,mid,nl,nr,ky);
160     else if(nl>mid) return get_pre(o<<1|1,mid+1,r,nl,nr,ky);
161     get_pre(o<<1,l,mid,nl,mid,ky),get_pre(o<<1|1,mid+1,r,mid+1,nr,ky);
162 }
163 void get_next(int o,int l,int r,int nl,int nr,int ky)
164 {
165     //debug(rt[o]);printf("\n");
166     if(nl==l&&r==nr)    return getnext(rt[o],ky);
167     int mid=l+r>>1;
168     if(nr<=mid) return get_next(o<<1,l,mid,nl,nr,ky);
169     else if(nl>mid) return get_next(o<<1|1,mid+1,r,nl,nr,ky);
170     get_next(o<<1,l,mid,nl,mid,ky),get_next(o<<1|1,mid+1,r,mid+1,nr,ky);
171 }
172 int get_kth(int nl,int nr,int k)
173 {
174     int l=0,r=1e8+1,ans=0;
175     while(l<=r)
176     {
177         int mid=l+r>>1;
178         if(get_rank(1,1,n,nl,nr,mid)+1<=k)  l=mid+1,ans=mid;
179         else    r=mid-1;
180     }
181     return ans;
182 }
183 int main(void)
184 {
185     n=read(),m=read();
186     for(int i=1;i<=n;i++)
187         val[i]=read(),update(1,1,n,i,val[i]);
188     int op,l,r,x;
189     while(m--)
190     {
191         op=read(),l=read(),r=read();
192         if(op==3)
193             {update(1,1,n,l,r,1);val[l]=r;continue;}
194         x=read();
195         if(op==1)
196             ans=get_rank(1,1,n,l,r,x)+1;
197         else if(op==2)
198             ans=get_kth(l,r,x);
199         else if(op==4)
200             ans=-0x3f3f3f3f,get_pre(1,1,n,l,r,x);
201         else
202             ans=0x3f3f3f3f,get_next(1,1,n,l,r,x);
203         printf("%d\n",ans);
204     }
205 }

 

以上是关于bzoj3196: Tyvj 1730 二逼平衡树 树套树的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3196: Tyvj 1730 二逼平衡树

bzoj3196: Tyvj 1730 二逼平衡树

bzoj3196: Tyvj 1730 二逼平衡树

bzoj 3196: Tyvj 1730 二逼平衡树

bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

Bzoj3196 Tyvj 1730 二逼平衡树