标签:min 数据结构 最大的 sample include 范围 pushd 树套树 进化
Treap=Tree+Heap 起名的人非常有才
Treap是啥?
一棵二叉搜索树可能退化成链,那样各种操作的效率都比较低
于是可爱的Treap在每个节点原先值v的基础上加了一个随机数rnd,树的形态要满足是rnd的大根堆或小根堆
可以说是普通BST的进化版吧。
Q:为什么rnd要满足是大根堆或小根堆,不能是二叉搜索树吗?
A:不能!二叉搜索树旋转时一直满足是二叉搜索树,也就是说值与值之间的相对顺序不管怎么转都是一定的。Treap本身就是二叉搜索树,在每插入一个新节点时,该节点在二叉搜索树中的相对位置是一定的。根据v而插入的位置,若此时rnd不满足二叉搜索树,那怎么旋转都无法满足是rnd的二叉搜索树。
Q:那为什么rnd可满足大根堆或小根堆呢?
A:以大根堆为例。用类似循环不定式证明。
i)假设在插入一个点前树的形态已满足是rnd的大根堆。按照v先将这个点p插到treap中,如果v比其父节点pa的rnd值大,就把p旋转到pa的位置。pa旋到下面后,连上了p的一个子节点son。因为原来rnd满足大根堆,那么pa的rnd一定大于son的rnd,此时p及其子树满足是rnd的大根堆。以此类推不断把p向上旋转,直到p的rnd小于pa的rnd。此时整棵树满足是rnd的大根堆,也就满足treap的要求
ii)当只有一个节点时,显然满足treap要求
Treap基本操作
维护一个有序序列,支持插入、删除,询问前驱后继、排名,区间加减等
Treap V.S. Splay
不像splay用起来那样方便,也没有splay像reverse之类的操作,但是比较好写,常数也稍微小一点
Treap V.S. 红黑树
跟红黑树相比,红黑树的效率更稳定(毕竟Treap有随机数),但红黑树写起来太过复杂。
用STL的set很方便,但不能查排名等信息
模板(洛谷P3369)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #define INF 100000007 5 #define P1 39916801 6 #define P2 4987657 7 using namespace std; 8 9 typedef long long ll; 10 const int N = 100005; 11 struct node{ 12 int v,rnd,size; 13 node *ch[2],*pa; 14 }pool[N]; 15 int cnt; 16 17 int rr; 18 int Getrnd(){ //生成随机数 19 rr=((ll)rr*P1)%P2; 20 return rr; 21 } 22 23 struct treap{ 24 node *root,*rf; 25 int size(node *p){ 26 return p?p->size:0; 27 } 28 void update(node *p){ 29 p->size=size(p->ch[0])+size(p->ch[1])+1; 30 } 31 void rotate(node *p,int t){ 32 node *son=p->ch[!t],*pa=p->pa,*gp=p->pa->pa; 33 pa->ch[t]=son; 34 if(son) son->pa=pa; 35 p->ch[!t]=pa; 36 pa->pa=p; 37 p->pa=gp; 38 gp->ch[pa==gp->ch[1]]=p; 39 if(root==pa) root=p; 40 update(pa);update(p); 41 } 42 void insert(node *p,node *nd){ 43 int f=p->v<nd->v?1:0; 44 if(!p->ch[f]){ 45 p->ch[f]=nd; 46 nd->pa=p; 47 } 48 else insert(p->ch[f],nd); 49 update(p); 50 if(p->ch[f]->rnd>p->rnd) rotate(p->ch[f],f); 51 } 52 void Ins(int v){ 53 node *nd=&pool[++cnt]; 54 nd->v=v;nd->size=1;nd->rnd=Getrnd(); 55 nd->pa=nd->ch[0]=nd->ch[1]=NULL; 56 if(root) insert(root,nd); 57 else{ 58 root=nd; 59 root->pa=rf; 60 rf->ch[1]=root; 61 } 62 } 63 void del(node *p,int v){ //删除 注意向上更新处容易写错 64 if(p->v==v){ 65 if(!p->ch[0] || !p->ch[1]){ 66 node *pa=p->pa,*son=p->ch[p->ch[0]?0:1]; 67 pa->ch[p==pa->ch[1]]=son; 68 if(son) son->pa=pa; 69 if(p==root) root=son; 70 while(pa) 71 update(pa),pa=pa->pa; 72 } 73 else{ 74 int f=p->ch[1]->rnd>p->ch[0]->rnd?1:0; 75 rotate(p->ch[f],f);del(p,v); 76 } 77 } 78 else del(p->ch[v>p->v],v); 79 } 80 int rank(node *p,int v){ //比v小的节点个数 81 if(!p) return 0; 82 if(p->v<v) return 1+size(p->ch[0])+rank(p->ch[1],v); 83 else return rank(p->ch[0],v); 84 } 85 int find(node *p,int k){ //询问排名第k的节点值 86 if(size(p->ch[0])>=k) return find(p->ch[0],k); 87 if(size(p->ch[0])==k-1) return p->v; 88 return find(p->ch[1],k-size(p->ch[0])-1); 89 } 90 int pre(node *p,int v){//前驱 91 if(!p) return -INF; 92 if(v>p->v) return max(p->v,pre(p->ch[1],v)); 93 else return pre(p->ch[0],v); 94 } 95 int sub(node *p,int v){//后继 96 if(!p) return INF; 97 if(v<p->v) return min(p->v,sub(p->ch[0],v)); 98 else return sub(p->ch[1],v); 99 } 100 void inorder(node *p){ 101 if(p->ch[0]) inorder(p->ch[0]); 102 printf("%d ",p->v); 103 if(p->ch[1]) inorder(p->ch[1]); 104 } 105 }tr; 106 107 int main() 108 { 109 int n,opt,x; 110 scanf("%d",&n); 111 112 tr.rf=&pool[++cnt]; 113 while(n--){ 114 scanf("%d%d",&opt,&x); 115 switch(opt){ 116 case 1:tr.Ins(x);break;//插入 117 case 2:tr.del(tr.root,x);break;//删除 118 case 3:printf("%d\n",tr.rank(tr.root,x)+1);break;//某数排名=比该数小的个数+1 119 case 4:printf("%d\n",tr.find(tr.root,x));break;//排名x的数 120 case 5:printf("%d\n",tr.pre(tr.root,x));break;//前驱 121 case 6:printf("%d\n",tr.sub(tr.root,x));break;//后继 122 default:break; 123 } 124 } 125 126 return 0; 127 }
应用
·普通应用
i)bzoj3173 最长上升子序列
100%的数据 n<=100000
代码:(这是几个月前写的,代码风格不太一样)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<iostream> 4 #include<algorithm> 5 #include<string.h> 6 #define INF 2147483647 7 using namespace std; 8 9 const int MAXN=100005; 10 struct node 11 { 12 int size,d,rnd; 13 node *parent,*lson,*rson; 14 }pool[MAXN],*root; 15 int cnt,cnt1,n; 16 int c[MAXN],dp[MAXN],ans[MAXN]; 17 18 void update(node *p) 19 { 20 p->size=1; 21 if(p->lson) p->size+=p->lson->size; 22 if(p->rson) p->size+=p->rson->size; 23 } 24 25 void right_rotate(node *p) 26 { 27 node *lson=p->lson,*parent=p->parent,*gp=p->parent->parent; 28 parent->rson=lson; 29 if(lson) lson->parent=parent; 30 p->lson=parent;parent->parent=p; 31 p->parent=gp; 32 if(gp) 33 { 34 if(parent==gp->lson) gp->lson=p; 35 else gp->rson=p; 36 } 37 else root=p; 38 update(parent); 39 update(p); 40 } 41 42 void left_rotate(node *p) 43 { 44 node *rson=p->rson,*parent=p->parent,*gp=p->parent->parent; 45 parent->lson=rson; 46 if(rson) rson->parent=parent; 47 p->rson=parent;parent->parent=p; 48 p->parent=gp; 49 if(gp) 50 { 51 if(parent==gp->lson) gp->lson=p; 52 else gp->rson=p; 53 } 54 else root=p; 55 update(parent); 56 update(p); 57 } 58 59 int size(node *p) 60 { 61 if(p==NULL) return 0; 62 return p->size; 63 } 64 65 void insert(node *p,node *newnode,int rank) 66 { 67 if(size(p->lson)+1>=rank) 68 { 69 if(p->lson==NULL) 70 { 71 p->lson=newnode; 72 newnode->parent=p; 73 p->size++; 74 return; 75 } 76 insert(p->lson,newnode,rank); 77 p->size++; 78 if(p->lson->rnd>p->rnd) left_rotate(p->lson); 79 } 80 else 81 { 82 if(p->rson==NULL) 83 { 84 p->rson=newnode; 85 newnode->parent=p; 86 p->size++; 87 return; 88 } 89 insert(p->rson,newnode,rank-size(p->lson)-1); 90 p->size++; 91 if(p->rson->rnd>p->rnd) right_rotate(p->rson); 92 } 93 } 94 95 int main() 96 { 97 int i,a,j; 98 node *tmp; 99 scanf("%d",&n); 100 srand(1); 101 for(i=1;i<=n;i++) 102 { 103 scanf("%d",&a); 104 tmp=&pool[++cnt]; 105 tmp->d=i; 106 srand(rand()%10007); 107 tmp->rnd=rand()%10007; 108 tmp->size=1; 109 if(i==1) root=tmp; 110 else insert(root,tmp,++a); 111 } 112 113 cnt1=0; 114 memset(dp,127,sizeof(dp)); 115 int len=0,t; 116 dp[0]=-INF; 117 for(i=1;i<=n;i++) 118 { 119 t=upper_bound(dp,dp+len+1,c[i])-dp; 120 if(dp[t-1]<=c[i]) 121 { 122 dp[t]=min(dp[t],c[i]); 123 ans[c[i]]=t; 124 len=max(len,t); 125 } 126 } 127 128 ans[0]=0; 129 for(i=1;i<=n;i++) 130 { 131 ans[i]=max(ans[i],ans[i-1]); 132 printf("%d\n",ans[i]); 133 } 134 135 return 0; 136 }
ii) noip2017提高day2-3 列队
(洛谷P3960)
n行以及最后一列各维护一个treap(这样共n+1个),反着来考虑,把每次出队的人加会队列
需要注意的是每行最后一列的要加到第n+1个treap中
细节还挺多的,要想清楚
代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #define P1 39916801 5 #define P2 4987657 6 using namespace std; 7 8 typedef long long ll; 9 const int N = 300005; 10 11 int rr=1; 12 int Get_rnd(){ 13 rr=((ll)rr*P2)%P1; 14 return rr; 15 } 16 17 struct node{ 18 int v,rnd,id,lazy,size; 19 node *pa,*ch[2]; 20 }pool[4*N],*tmp,*num[N]; 21 int cnt; 22 23 struct treap{ 24 node *root,*rf; 25 int size(node *p){ 26 if(p) return p->size; 27 return 0; 28 } 29 void update(node *p){ 30 p->size=1+size(p->ch[0])+size(p->ch[1]); 31 } 32 void pushdown(node *p){ 33 if(p->lazy){ 34 p->v+=p->lazy; 35 if(p->ch[0]) p->ch[0]->lazy+=p->lazy; 36 if(p->ch[1]) p->ch[1]->lazy+=p->lazy; 37 p->lazy=0; 38 } 39 } 40 void rotate(node *p,int t){ 41 node *son=p->ch[!t],*pa=p->pa,*gp=p->pa->pa; 42 pa->ch[t]=son; 43 if(son) son->pa=pa; 44 pa->pa=p; 45 p->ch[!t]=pa; 46 p->pa=gp; 47 gp->ch[pa==gp->ch[1]]=p; 48 if(pa==root) root=p; 49 update(pa);update(p); 50 } 51 void insert(node *p,node *nd,int t){ 52 pushdown(p); 53 int f=0; 54 if(nd->v>p->v) f=1; 55 if(p->ch[f]==NULL){ 56 p->ch[f]=nd; 57 nd->pa=p; 58 nd->size=1;nd->lazy=0; 59 } 60 else insert(p->ch[f],nd,t); 61 update(p); 62 if(f==0 && t==0){ 63 p->v++; 64 if(p->ch[1]) p->ch[1]->lazy++; 65 } 66 if(p->ch[f]->rnd>p->rnd) rotate(p->ch[f],f); 67 } 68 void Ins(node *nd,int t){ 69 if(root==NULL){ 70 root=nd; 71 root->pa=rf; 72 rf->ch[1]=root; 73 } 74 else insert(root,nd,t); 75 } 76 void add(node *p,int v){ 77 pushdown(p); 78 if(p->v>=v) { 79 p->v++; 80 if(p->ch[1]) p->ch[1]->lazy++; 81 if(p->ch[0]) add(p->ch[0],v); 82 } 83 else if(p->ch[1]) add(p->ch[1],v); 84 } 85 void del(node *p){ 86 pushdown(p); 87 if(p->ch[1]) del(p->ch[1]); 88 else{ 89 node *son=p->ch[0],*pa=p->pa; 90 pa->ch[1]=son;/**/ 91 if(son) son->pa=pa; 92 if(root==p) root=son; 93 } 94 update(p); 95 } 96 node *last(node *p){ 97 pushdown(p); 98 if(p->ch[1]) return last(p->ch[1]); 99 return p; 100 } 101 void update_all(node *p){ 102 pushdown(p); 103 if(p->ch[0]) update_all(p->ch[0]); 104 if(p->ch[1]) update_all(p->ch[1]); 105 } 106 void inorder(node *p){ 107 pushdown(p); 108 if(p->ch[0]) inorder(p->ch[0]); 109 printf("%d ",p->v); 110 if(p->ch[1]) inorder(p->ch[1]); 111 } 112 }tr[N]; 113 114 int n,m,Q; 115 int xx[N],yy[N]; 116 117 int main() 118 { 119 int i,j; 120 scanf("%d%d%d",&n,&m,&Q); 121 for(i=1;i<=Q;i++) 122 scanf("%d%d",&xx[i],&yy[i]); 123 124 for(i=1;i<=n+1;i++) 125 tr[i].rf=&pool[++cnt]; 126 127 for(i=Q;i>0;i--){ 128 if(tr[n+1].root && tr[n+1].last(tr[n+1].root)->v==n){ 129 tmp=tr[n+1].last(tr[n+1].root); 130 tr[n+1].del(tr[n+1].root); 131 } 132 else tmp=&pool[++cnt]; 133 134 tmp->v=yy[i];tmp->id=xx[i]; 135 tmp->size=1;tmp->lazy=0; 136 tmp->ch[0]=tmp->ch[1]=tmp->pa=NULL; 137 tmp->rnd=Get_rnd(); 138 tr[xx[i]].Ins(tmp,0); 139 140 num[i]=tmp; 141 if(tr[n+1].root) tr[n+1].add(tr[n+1].root,xx[i]); 142 143 tmp=tr[xx[i]].last(tr[xx[i]].root); 144 if(tmp->v==m){ 145 tr[xx[i]].del(tr[xx[i]].root); 146 tmp->v=xx[i];tmp->id=n+1; 147 tmp->size=1;tmp->lazy=0; 148 tmp->ch[0]=tmp->ch[1]=tmp->pa=NULL; 149 tmp->rnd=Get_rnd(); 150 tr[n+1].Ins(tmp,1); 151 } 152 } 153 154 ll ret=0; 155 for(i=1;i<=n+1;i++) 156 if(tr[i].root) tr[i].update_all(tr[i].root); 157 for(i=1;i<=Q;i++){ 158 ret=0; 159 if(num[i]->id==n+1) 160 ret=(ll)num[i]->v*m; 161 else 162 ret=((ll)num[i]->id-1)*m+num[i]->v; 163 printf("%lld\n",ret);/**/ 164 } 165 166 return 0; 167 }
·树套树
i)三维偏序
树状数组套treap,树状数组每个点后都建一棵treap
洛谷P3810 (代码微丑,多多包涵 + 这是一周前写的,代码风格也略微不一样)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<string.h> 6 #define P1 39916801 7 #define P2 4987657 8 using namespace std; 9 10 typedef long long ll; 11 const int N = 100005; 12 struct data{ 13 int a,b,c; 14 int flag,num; 15 bool operator < (const data &x){ 16 if(a!=x.a) return x.a<a; 17 if(b!=x.b) return x.b<b; 18 return x.c<c; 19 } 20 }d[N]; 21 int ans[N],n; 22 int dd[N]; 23 bool cmp1(int x,int y){ 24 return d[x].a<d[y].a; 25 } 26 bool cmp2(int x,int y){ 27 return d[x].b<d[y].b; 28 } 29 bool cmp3(int x,int y){ 30 return d[x].c<d[y].c; 31 } 32 bool cmp(data x,data y){ 33 return y<x; 34 } 35 int lowbit(int x){ 36 return x&(-x); 37 } 38 39 int rr=1; 40 int Getrnd(){ 41 rr=((ll)rr*P1)%P2; 42 return rr; 43 } 44 45 struct node{ 46 int v,rnd,id; 47 int size; 48 node *parent,*ch[2]; 49 }pool[20*N],*root[N]; 50 int cnt; 51 int size(node *p){ 52 if(p) return p->size; 53 return 0; 54 } 55 void update(node *p){ 56 p->size=size(p->ch[0])+size(p->ch[1])+1; 57 } 58 void rotate(node *p,int type){ 59 node *son=p->ch[!type],*parent=p->parent,*gp=p->parent->parent; 60 parent->ch[type]=son; 61 if(son) son->parent=parent; 62 p->ch[!type]=parent; 63 parent->parent=p; 64 p->parent=gp; 65 if(gp) gp->ch[parent==gp->ch[1]]=p; 66 else root[p->id]=p; 67 update(parent); 68 update(p); 69 } 70 void insert(node *p,node *newnode){ 71 int f=0; 72 if(newnode->v>p->v) f=1; 73 if(p->ch[f]==NULL){ 74 p->ch[f]=newnode; 75 newnode->size=1; 76 newnode->parent=p; 77 } 78 else insert(p->ch[f],newnode); 79 update(p); 80 if(p->ch[f]->rnd>p->rnd) rotate(p->ch[f],f); 81 } 82 int find(node *p,int key){ 83 int ret=0; 84 if(p->v<=key){ 85 ret=ret+1+size(p->ch[0]); 86 if(p->ch[1]) ret+=find(p->ch[1],key); 87 } 88 else { 89 if(p->ch[0]) ret+=find(p->ch[0],key); 90 } 91 return ret; 92 } 93 int Getans(int x){ 94 int ret=0,y; 95 y=d[x].b; 96 while(y>0){ 97 if(root[y]) ret+=find(root[y],d[x].c); 98 y-=lowbit(y); 99 } 100 return ret; 101 } 102 void add(int x){ 103 int y=d[x].b; 104 while(y<=n){ 105 node *newnode=&pool[++cnt]; 106 newnode->v=d[x].c;newnode->size=1;newnode->id=y; 107 newnode->rnd=Getrnd(); 108 if(root[y]) insert(root[y],newnode); 109 else root[y]=newnode; 110 y+=lowbit(y); 111 } 112 } 113 114 int main() 115 { 116 int k,i,j,tot,pre; 117 scanf("%d%d",&n,&k); 118 for(i=1;i<=n;i++){ 119 scanf("%d%d%d",&d[i].a,&d[i].b,&d[i].c); 120 dd[i]=i; 121 } 122 sort(dd+1,dd+1+n,cmp1); 123 tot=1; 124 pre=d[dd[1]].a;d[dd[1]].a=tot; 125 for(i=2;i<=n;i++){ 126 if(pre!=d[dd[i]].a) tot++; 127 pre=d[dd[i]].a; 128 d[dd[i]].a=tot; 129 } 130 sort(dd+1,dd+1+n,cmp2); 131 tot=1; 132 pre=d[dd[1]].b;d[dd[1]].b=tot; 133 for(i=2;i<=n;i++){ 134 if(pre!=d[dd[i]].b) tot++; 135 pre=d[dd[i]].b; 136 d[dd[i]].b=tot; 137 } 138 sort(dd+1,dd+1+n,cmp3); 139 tot=1; 140 pre=d[dd[1]].c;d[dd[1]].c=tot; 141 for(i=2;i<=n;i++){ 142 if(pre!=d[dd[i]].c) tot++; 143 pre=d[dd[i]].c; 144 d[dd[i]].c=tot; 145 } 146 sort(d+1,d+1+n,cmp); 147 148 for(i=1;i<=n;i++){ 149 j=1; 150 while(i<n && d[i].a==d[i+1].a && d[i].b==d[i+1].b && d[i].c==d[i+1].c) 151 i++,j++; 152 d[i].flag=1;d[i].num=j; 153 } 154 155 for(i=1;i<=n;i++){ 156 if(d[i].flag==1) ans[Getans(i)]+=d[i].num; 157 add(i); 158 } 159 160 for(i=0;i<n;i++) 161 printf("%d\n",ans[i]); 162 163 return 0; 164 }
ii)二逼平衡树 bzoj3196
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)
第一行两个数 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的后继
对于操作1,2,4,5各输出一行,表示查询结果
1.n和m的数据范围:n,m<=50000
2.序列中每个数的数据范围:[0,1e8]
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #define P1 39916801 5 #define P2 4987657 6 using namespace std; 7 8 typedef long long ll; 9 const int N = 50005; 10 struct node{ 11 int v,rnd,size; 12 node *pa,*ch[2]; 13 }pool[20*N]; 14 int cnt,a[N]; 15 16 int rr=1; 17 int Get_rnd(){ 18 rr=((((ll)rr*P2)%P1)*P1)%P2; 19 return rr; 20 } 21 22 struct treap{ 23 node *root,*rf; 24 int size(node *p){ 25 if(p) return p->size; 26 return 0; 27 } 28 void update(node *p){ 29 p->size=1+size(p->ch[0])+size(p->ch[1]); 30 } 31 void rotate(node *p,int t){ 32 node *son=p->ch[!t],*pa=p->pa,*gp=pa->pa; 33 pa->ch[t]=son; 34 if(son) son->pa=pa; 35 p->ch[!t]=pa; 36 pa->pa=p; 37 p->pa=gp; 38 gp->ch[pa==gp->ch[1]]=p; 39 if(pa==root) root=p; 40 update(pa);update(p); 41 } 42 void insert(node *p,node *nd){ 43 int f=0; 44 if(nd->v>p->v) f=1; 45 if(p->ch[f]==NULL){ 46 p->ch[f]=nd; 47 nd->pa=p; 48 } 49 else insert(p->ch[f],nd); 50 update(p); 51 if(p->ch[f]->rnd>p->rnd) rotate(p->ch[f],f); 52 } 53 node *find(node *p,int k){ 54 if(p->v>k) return find(p->ch[1],k); 55 else if(p->v==k) return p; 56 else return find(p->ch[0],k); 57 } 58 node *del(node *p,int v){/**/ 59 if(v==p->v){ 60 if(!p->ch[0] || !p->ch[1]){ 61 int f=0; 62 if(p->ch[1]) f=1; 63 node *son=p->ch[f],*pa=p->pa; 64 pa->ch[p==pa->ch[1]]=son; 65 if(son) son->pa=pa; 66 if(root==p) root=son; 67 node *q=pa; 68 while(q!=NULL) 69 update(q),q=q->pa; 70 return p; 71 } 72 else { 73 int f=0; 74 if(p->ch[0]->rnd<p->ch[1]->rnd) f=1; 75 rotate(p->ch[f],f); 76 return del(p,v); 77 } 78 } 79 else if(v<p->v) { 80 node *q=del(p->ch[0],v); 81 return q; 82 } 83 else { 84 node *q=del(p->ch[1],v); 85 return q; 86 } 87 } 88 void remove(int x,int y){ 89 node *p=del(root,x); 90 p->v=y;p->size=1; 91 p->pa=NULL;p->ch[0]=NULL;p->ch[1]=NULL; 92 if(root) insert(root,p);/**/ 93 else{ 94 root=p; 95 rf->ch[1]=root; 96 root->pa=rf; 97 } 98 } 99 int rank(node *p,int v){ 100 int ret=0; 101 if(p->v<v){ 102 ret+=1+size(p->ch[0]); 103 if(p->ch[1]) ret+=rank(p->ch[1],v); 104 } 105 else if(p->ch[0]) ret+=rank(p->ch[0],v); 106 return ret; 107 } 108 int sub(node *p,int v){ 109 int ret=2147483647; 110 if(p->v>v){ 111 ret=min(ret,p->v); 112 if(p->ch[0]) ret=min(ret,sub(p->ch[0],v)); 113 } 114 else if(p->ch[1]) ret=min(ret,sub(p->ch[1],v)); 115 return ret; 116 } 117 int pre(node *p,int v){ 118 int ret=-2147483647; 119 if(p->v<v){ 120 ret=max(ret,p->v); 121 if(p->ch[1]) ret=max(ret,pre(p->ch[1],v)); 122 } 123 else if(p->ch[0]) ret=max(ret,pre(p->ch[0],v)); 124 return ret; 125 } 126 void inorder(node *p){ 127 if(p->ch[0]) inorder(p->ch[0]); 128 printf("%d ",p->v); 129 if(p->ch[1]) inorder(p->ch[1]); 130 } 131 }; 132 133 struct tree{ 134 int l,r; 135 treap tr; 136 tree *left,*right; 137 }pool2[N*4],*rt; 138 int cnt2; 139 void Build(tree *p,int l,int r){ 140 p->l=l;p->r=r; 141 node *tmp=&pool[++cnt];p->tr.rf=tmp; 142 if(l==r) return; 143 int mid=(l+r)/2; 144 p->left=&pool2[++cnt2];p->right=&pool2[++cnt2]; 145 Build(p->left,l,mid); 146 Build(p->right,mid+1,r); 147 } 148 int q_rank(tree *p,int l,int r,int x){ 149 if(p->l==l && p->r==r){ 150 return p->tr.rank(p->tr.root,x); 151 } 152 if(p->left->r>=r) return q_rank(p->left,l,r,x); 153 else if(p->right->l<=l) return q_rank(p->right,l,r,x); 154 else return q_rank(p->left,l,p->left->r,x)+q_rank(p->right,p->right->l,r,x); 155 } 156 int q_pre(tree *p,int l,int r,int x){ 157 if(p->l==l && p->r==r) 158 return p->tr.pre(p->tr.root,x); 159 if(p->left->r>=r) return q_pre(p->left,l,r,x); 160 else if(p->right->l<=l) return q_pre(p->right,l,r,x); 161 else return max(q_pre(p->left,l,p->left->r,x),q_pre(p->right,p->right->l,r,x)); 162 } 163 int q_sub(tree *p,int l,int r,int x){ 164 if(p->l==l && p->r==r) 165 return p->tr.sub(p->tr.root,x); 166 if(p->left->r>=r) return q_sub(p->left,l,r,x); 167 else if(p->right->l<=l) return q_sub(p->right,l,r,x); 168 else return min(q_sub(p->left,l,p->left->r,x),q_sub(p->right,p->right->l,r,x)); 169 } 170 void add(tree *p,int l,int x){ 171 node *tmp=&pool[++cnt]; 172 tmp->v=x;tmp->size=1;tmp->rnd=Get_rnd(); 173 if(p->tr.root!=NULL) p->tr.insert(p->tr.root,tmp); 174 else { 175 p->tr.root=tmp; 176 p->tr.rf->ch[1]=p->tr.root; 177 p->tr.root->pa=p->tr.rf; 178 } 179 if(p->l==l && p->r==l) return; 180 if(p->right->l<=l) add(p->right,l,x); 181 else add(p->left,l,x); 182 } 183 void change(tree *p,int l,int x){ 184 p->tr.remove(a[l],x); 185 if(p->l==l && p->r==l) return; 186 if(p->right->l<=l) change(p->right,l,x); 187 else change(p->left,l,x); 188 } 189 190 191 int main() 192 { 193 int n,m,i,opt,x,y,z,l,r,mid; 194 scanf("%d%d",&n,&m); 195 for(i=1;i<=n;i++) scanf("%d",&a[i]); 196 197 //build 198 rt=&pool2[++cnt2]; 199 Build(rt,1,n); 200 for(i=1;i<=n;i++) 201 add(rt,i,a[i]); 202 203 while(m--){ 204 scanf("%d",&opt); 205 if(opt==1){ 206 scanf("%d%d%d",&x,&y,&z); 207 printf("%d\n",q_rank(rt,x,y,z)+1); 208 } 209 else if(opt==2){ 210 scanf("%d%d%d",&x,&y,&z); 211 l=0;r=1e8; 212 while(l<r){ 213 mid=(l+r+1)/2; 214 if(q_rank(rt,x,y,mid)+1<=z) l=mid; 215 else r=mid-1; 216 } 217 printf("%d\n",l); 218 } 219 else if(opt==3){ 220 scanf("%d%d",&x,&y); 221 change(rt,x,y); 222 a[x]=y; 223 } 224 else if(opt==4){ 225 scanf("%d%d%d",&x,&y,&z); 226 printf("%d\n",q_pre(rt,x,y,z)); 227 } 228 else{ 229 scanf("%d%d%d",&x,&y,&z); 230 printf("%d\n",q_sub(rt,x,y,z)); 231 } 232 } 233 234 return 0; 235 }
标签:min 数据结构 最大的 sample include 范围 pushd 树套树 进化
原文地址:http://www.cnblogs.com/lindalee/p/7896594.html