bzoj3196 二逼平衡树 树套树(线段树套Treap)

Tyvj 1730 二逼平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 4697  Solved: 1798
[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可能为负数

 

Source

 

题解:

  这道题目的第二个操作没什么办法,唉,记得当时有log n 的算法的,现在只有log^2n的算法,o( ̄ヘ ̄o#)

  线段树套平衡树吧,这里选的是Treap

  1 #include<cstring>
  2 #include<cmath>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<cstdio>
  6 
  7 #define N 200007
  8 #define M 4000007
  9 #define inf 2000000007
 10 using namespace std;
 11 inline int read()
 12 {
 13     int x=0,f=1;char ch=getchar();
 14     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
 15     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
 16     return x*f;
 17 }
 18 
 19 int n,m,ans,sz;
 20 int ls[M],rs[M],rnd[M],val[M],siz[M],ct[M];
 21 int root[N],a[N];
 22 
 23 inline int rand()
 24 {
 25     static int seed=2333;
 26     return seed=(int)((((seed^998244353)+19260817ll)*19890604ll)%1000000007);
 27 }
 28 void update(int p){siz[p]=siz[ls[p]]+siz[rs[p]]+ct[p];}
 29 void rturn(int &p){int t=ls[p];ls[p]=rs[t];rs[t]=p;siz[t]=siz[p];update(p);p=t;}
 30 void lturn(int &p){int t=rs[p];rs[p]=ls[t];ls[t]=p;siz[t]=siz[p];update(p);p=t;}
 31 void ins(int &p,int z)
 32 {
 33     if (!p)
 34     {
 35         p=++sz;
 36         siz[p]=ct[p]=1;
 37         val[p]=z;
 38         rnd[p]=rand();
 39         return;
 40     }
 41     siz[p]++;
 42     if (z==val[p])ct[p]++;
 43     else if (z<val[p])
 44          {
 45               ins(ls[p],z);
 46              if (rnd[ls[p]]<rnd[p]) rturn(p);
 47          }
 48     else 
 49          {
 50               ins(rs[p],z);
 51              if (rnd[rs[p]]<rnd[p]) lturn(p); 
 52          }
 53 }
 54 void del(int &p,int x)
 55 {
 56     if (p==0) return;
 57     if (val[p]==x)
 58     {
 59         if (ct[p]>1) ct[p]--,siz[p]--;//如果有多个直接减一即可。
 60         else
 61         {
 62             if (ls[p]==0||rs[p]==0) p=ls[p]+rs[p];//单节点或者空的话直接儿子移上来或者删去即可。
 63             else if (rnd[ls[p]]<rnd[rs[p]]) rturn(p),del(p,x);
 64             else lturn(p),del(p,x); 
 65         }
 66     }
 67     else if (x>val[p]) siz[p]--,del(rs[p],x);
 68     else siz[p]--,del(ls[p],x);
 69 }
 70 void build(int p,int l,int r,int x,int z)
 71 {
 72     ins(root[p],z);
 73     if (l==r) return;
 74     int mid=(l+r)>>1;
 75     if(x<=mid)build(p<<1,l,mid,x,z);
 76     else build(p<<1|1,mid+1,r,x,z);
 77 }
 78 void get_rank_sec(int p,int z)
 79 {
 80     if (!p) return;//没有不需要。
 81     if (z==val[p]) ans+=siz[ls[p]];
 82     else if (z<val[p]) get_rank_sec(ls[p],z);
 83     else
 84     {
 85         ans+=siz[ls[p]]+ct[p];
 86         get_rank_sec(rs[p],z); 
 87     }
 88 }
 89 void get_rank_fir(int p,int l,int r,int x,int y,int z)
 90 {
 91     if (l==x&&r==y)
 92     {
 93         get_rank_sec(root[p],z);
 94         return;
 95     }
 96     int mid=(l+r)>>1;
 97     if (y<=mid) get_rank_fir(p<<1,l,mid,x,y,z);
 98     else if (x>mid) get_rank_fir(p<<1|1,mid+1,r,x,y,z);
 99     else get_rank_fir(p<<1,l,mid,x,mid,z),get_rank_fir(p<<1|1,mid+1,r,mid+1,y,z);
100 }
101 void mid_to_find_index(int x,int y,int z)
102 {
103     int l=0,r=inf,res;
104     while(l<=r)
105     {
106         int mid=(l+r)>>1;
107         ans=1;get_rank_fir(1,1,n,x,y,mid);
108         if(ans<=z){l=mid+1;res=mid;}
109         else r=mid-1;
110         }
111     printf("%d\n",res);
112 }
113 void modify(int p,int l,int r,int x,int yl,int xz)
114 {
115     del(root[p],yl);
116     ins(root[p],xz);
117     if (l==r) return;
118     int mid=(l+r)>>1;
119     if (x<=mid)modify(p<<1,l,mid,x,yl,xz);
120     else modify(p<<1|1,mid+1,r,x,yl,xz);
121 }
122 void find_before_sec(int p,int z)
123 {
124     if (!p) return;
125     if (val[p]<z)
126     {
127         ans=max(ans,val[p]);
128         find_before_sec(rs[p],z);
129     }
130     else find_before_sec(ls[p],z);
131 }
132 void find_before_fir(int p,int l,int r,int x,int y,int z)
133 {
134     if (l==x&&r==y)
135     {
136         find_before_sec(root[p],z);
137         return;
138     }
139     int mid=(l+r)>>1;
140     if (y<=mid) find_before_fir(p<<1,l,mid,x,y,z);
141     else if (x>mid) find_before_fir(p<<1|1,mid+1,r,x,y,z);
142     else find_before_fir(p<<1,l,mid,x,mid,z),find_before_fir(p<<1|1,mid+1,r,mid+1,y,z);
143 }
144 void find_after_sec(int p,int z)
145 {
146     if(!p)return;
147     if(val[p]>z)
148     {
149         ans=min(val[p],ans);
150         find_after_sec(ls[p],z);
151     }
152     else find_after_sec(rs[p],z);
153 }
154 void find_after_fir(int p,int l,int r,int x,int y,int z)
155 {
156     if (l==x&&r==y)
157     {
158         find_after_sec(root[p],z);
159         return;
160     }
161     int mid=(l+r)>>1;
162     if (y<=mid) find_after_fir(p<<1,l,mid,x,y,z);
163     else if (x>mid) find_after_fir(p<<1|1,mid+1,r,x,y,z);
164     else find_after_fir(p<<1,l,mid,x,mid,z),find_after_fir(p<<1|1,mid+1,r,mid+1,y,z);
165 }
166 int main()
167 {
168     n=read(),m=read();
169     for (int i=1;i<=n;i++)
170         a[i]=read(),build(1,1,n,i,a[i]);
171     while(m--)
172     {
173         int flag=read(),x,y,k;
174         switch(flag)
175         {
176             case 1:x=read(),y=read(),k=read(),ans=1,get_rank_fir(1,1,n,x,y,k),printf("%d\n",ans);break;
177             case 2:x=read(),y=read(),k=read(),mid_to_find_index(x,y,k);break;
178             case 3:x=read(),y=read(),modify(1,1,n,x,a[x],y),a[x]=y;break;
179             case 4:x=read(),y=read(),k=read(),ans=0,find_before_fir(1,1,n,x,y,k),printf("%d\n",ans);break;
180             case 5:x=read(),y=read(),k=read(),ans=inf,find_after_fir(1,1,n,x,y,k),printf("%d\n",ans);break;
181         }
182     }
183 }

 

posted @ 2017-12-29 09:10  Kaiser-  阅读(262)  评论(0编辑  收藏  举报