【bzoj3196-二逼平衡树】线段树套平衡树

【bzoj3196-二逼平衡树】线段树套平衡树

http://acm.hust.edu.cn/vjudge/problem/42297

【题目描述】

写一种数据结构,来维护一个有序数列,其中需要提供以下操作:

1.查询k在区间内的排名

2.查询区间内排名为k的值

3.修改某一位值上的数值

4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)

5.查询k在区间内的后继(后继定义为大于x,且最小的数)

【输入格式】

第一行两个数 n,m( n,m <= 50000 )表示长度为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的前驱(没有前驱输出no

opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]k的后继(没有后继输出no

【输出格式】

对于操作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、序列中每个数的数据范围:[0,1e8]

2、虽然原题没有,但事实上5操作的k可能为负数

 

 

这题我在bzoj上AC,在tvoj上最后两个点TLE(然而并不知道怎么优化)。

昨天中午打了一个中午,晚上调了一个钟,今天早上又调了两个钟。。呵呵。。

我的做法是在开一棵1~n的线段树t,每个节点(管理t[x].l~t[x].r)开一棵treap,把t[x].l~t[x].r的值全部放进去。为了防止找前驱后继的时候有问题,每棵treap上先放-Inf和Inf进去。

1.表示查询k在区间[l,r]的排名:用线段树找到[l,r]所需要用到的线段树上的节点,开一个数组存起来,然后一个个区间查询比k小的数的个数。

2.表示查询区间[l,r]内排名为k的数:mn和mx存下出现过的最小和最大的数是什么。二分一个数x,然后用1的方法看x的排名。

这里注意一个问题:找的是排名<=k的最大的数。

例如:1 2 3 3 3 5,查询3的排名是3,但是如果我们要找排名为4的数,答案依然是3。

3.单点修改:顺着线段树走下去,中途所经过的点,都要在它那棵treap上del原来的数,ins新数

4.找前驱:就在线段树上先找出所有要用到的点,再一个个进去找在这棵treap树上的前驱x,取最大值。

5.找后继:同上。

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 using namespace std;
  6 
  7 const int N=50010,TN=50000*16+100,Inf=(int)1e9;
  8 struct tr_node{
  9     int son[2],n,c,f,d;
 10 }c[2*TN];
 11 struct xd_node{
 12     int lc,rc,l,r,root;
 13 }t[2*2*N];
 14 int tl,cl,sl;
 15 int w[2*N],s[2*N];
 16 
 17 void updata(int x)
 18 {
 19     if(!x) return;
 20     int lc=c[x].son[0],rc=c[x].son[1];
 21     c[x].c=c[x].n+c[lc].c+c[rc].c;
 22 }
 23 
 24 void add(int d,int f)
 25 {
 26     cl++;
 27     c[cl].f=f;c[cl].d=d;
 28     c[cl].n=c[cl].c=1;
 29     c[cl].son[0]=c[cl].son[1]=0;
 30     if(d<c[f].d) c[f].son[0]=cl;
 31     else c[f].son[1]=cl;
 32     updata(f);//debug
 33 }
 34 
 35 int find_ip(int d,int id)
 36 {
 37     int x=t[id].root;
 38     while(c[x].d!=d)
 39     {
 40         if(d<c[x].d)
 41         {
 42             if(c[x].son[0]) x=c[x].son[0];
 43             else break;
 44         }
 45         else 
 46         {
 47             if(c[x].son[1]) x=c[x].son[1];
 48             else break;
 49         }
 50     }
 51     return x;
 52 }
 53 
 54 void rotate(int x)
 55 {
 56     int y=c[x].f,z=c[y].f,w,r,R;
 57     w=(c[y].son[0]==x) ? 1:0;
 58     
 59     r=c[x].son[w];R=y;
 60     c[R].son[1-w]=r;
 61     if(r) c[r].f=R;
 62     
 63     r=x;R=z;
 64     c[R].son[(c[z].son[0]==y) ? 0:1]=r;
 65     c[r].f=R;
 66     
 67     r=y;R=x;
 68     c[R].son[w]=r;
 69     c[r].f=R;
 70     
 71     updata(y);
 72     updata(x);
 73 }
 74 
 75 void splay(int x,int rt,int id)
 76 {
 77     while(c[x].f!=rt)
 78     {
 79         int y=c[x].f,z=c[y].f;
 80         if(z==rt) rotate(x);
 81         else
 82         {
 83             if((c[z].son[0]==y) == (c[y].son[0]==x)) rotate(y),rotate(x);
 84             else rotate(x),rotate(x);
 85         }
 86     }
 87     if(rt==0) t[id].root=x;
 88 }
 89 
 90 void ins(int d,int id)
 91 {
 92     int root=t[id].root;
 93     if(root==0) {add(d,0);t[id].root=cl;return;}
 94     int x=find_ip(d,id);
 95     if(c[x].d==d) c[x].n++;
 96     else add(d,x);
 97     updata(x);
 98     splay(x,0,id);
 99 }
100 
101 int build_xd_tree(int l,int r)
102 {
103     int x=++tl;
104     t[x].l=l;t[x].r=r;
105     t[x].lc=t[x].rc=0;
106     t[x].root=0;
107     if(l<r)
108     {
109         int mid=(l+r)>>1;
110         t[x].lc=build_xd_tree(l,mid);
111         t[x].rc=build_xd_tree(mid+1,r);
112         ins(-Inf,x);ins(Inf,x);
113         for(int i=l;i<=r;i++) ins(w[i],x);
114     }
115     else ins(-Inf,x),ins(Inf,x),ins(w[t[x].l],x);//l==r
116     return x;
117 }
118 
119 void find_xd_id(int x,int l,int r)
120 {
121     if(t[x].l==l && t[x].r==r) {s[++sl]=x;return;}
122     int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)>>1;
123     if(r<=mid) find_xd_id(lc,l,r);
124     else if(l>mid) find_xd_id(rc,l,r);
125     else  find_xd_id(lc,l,mid),find_xd_id(rc,mid+1,r);
126 }
127 
128 int find_qq(int d,int id)
129 {
130     int x=find_ip(d,id);splay(x,0,id);//debug splay(x,0,id)
131     if(c[x].d>=d && c[x].son[0])
132     {
133         x=c[x].son[0];
134         while(c[x].son[1]) x=c[x].son[1];
135     }
136     if(c[x].d>=d) x=0;
137     return x;
138 }
139 
140 int find_hj(int d,int id)
141 {
142     int x=find_ip(d,id);splay(x,0,id);//debug
143     if(c[x].d<=d && c[x].son[1])
144     {
145         x=c[x].son[1];
146         while(c[x].son[0]) x=c[x].son[0];
147     }
148     if(c[x].d<=d) x=0;
149     return x;
150 }
151 
152 void del(int d,int id)
153 {
154     int x=find_ip(d,id);splay(x,0,id);
155     if(c[x].n>=2) {c[x].n--;return;}
156     int x0=find_qq(d,id);
157     int x1=find_hj(d,id);
158     splay(x0,0,id);
159     splay(x1,x0,id);
160     c[x1].son[0]=0;
161     updata(x1);
162 }
163 
164 void change(int x,int p,int d)
165 {
166     if(t[x].l==t[x].r) 
167     {
168         del(w[p],x);ins(d,x);
169         return;
170     }
171     int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)>>1;
172     if(p<=mid) change(lc,p,d);
173     else change(rc,p,d);
174     del(w[p],x);ins(d,x);
175 }
176 
177 int find_rk(int d,int id)//the number of all that <d
178 {
179     int root=t[id].root;
180     int x=find_qq(d,id);
181     splay(x,0,id);
182     return c[c[x].son[0]].c-1+c[x].n;
183 }
184 
185 int opt1(int k,int l,int r)
186 {
187     int ans=0;
188     sl=0;find_xd_id(1,l,r);
189     for(int j=1;j<=sl;j++) 
190         ans+=find_rk(k,s[j]);
191     return ans+1;
192 }
193 
194 int minn(int x,int y){return x<y ? x:y;}
195 int maxx(int x,int y){return x>y ? x:y;}
196 
197 int find_rank(int k)
198 {
199     int ans=0;
200     for(int i=1;i<=sl;i++) 
201         ans+=find_rk(k,s[i]);
202     return ans+1;
203 }
204 
205 int main()
206 {
207     freopen("a.in","r",stdin);
208     freopen("a.out","w",stdout);
209     int n,m;
210     scanf("%d%d",&n,&m);
211     tl=0;cl=0;
212     int mn=Inf,mx=-Inf;
213     for(int i=1;i<=n;i++) 
214     {
215         scanf("%d",&w[i]);
216         mn=minn(mn,w[i]);
217         mx=maxx(mx,w[i]);
218     }
219     build_xd_tree(1,n);
220     for(int i=1;i<=m;i++)
221     {
222         int k,l,r,pos,opt;
223         scanf("%d",&opt);
224         if(opt!=3) scanf("%d%d%d",&l,&r,&k);
225         else scanf("%d%d",&pos,&k);
226         if(opt==1) 
227         {
228             int ans=0;
229                 sl=0;find_xd_id(1,l,r);
230             printf("%d\n",find_rank(k));
231         }
232         if(opt==2)
233         {
234             sl=0;find_xd_id(1,l,r);
235             int ll=mn,rr=mx;
236             while(ll!=rr)
237             {
238                 int mid=(ll+rr+1)>>1;
239                 int now=find_rank(mid);
240                 if(now<=k) ll=mid;//注意
241                 else rr=mid-1;
242             }
243             printf("%d\n",ll);
244         }
245         if(opt==3)
246         {
247             change(1,pos,k);
248             w[pos]=k;
249             mn=minn(mn,k);
250             mx=maxx(mx,k);
251         }
252         if(opt==4)
253         {
254             int ans=-Inf;
255             sl=0;find_xd_id(1,l,r);
256             for(int j=1;j<=sl;j++) ans=maxx(ans,c[find_qq(k,s[j])].d);    
257             if(ans!=-Inf) printf("%d\n",ans);
258             else printf("no\n");
259         }
260         if(opt==5)
261         {
262             int ans=Inf;
263             sl=0;find_xd_id(1,l,r);
264             for(int j=1;j<=sl;j++) ans=minn(ans,c[find_hj(k,s[j])].d);
265             if(ans!=Inf) printf("%d\n",ans);
266             else printf("no\n");
267         }
268     }
269     return 0;
270 }

 

posted @ 2016-08-10 10:24 拦路雨偏似雪花 阅读( ...) 评论( ...) 编辑 收藏
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值