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 MBSubmit: 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
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
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 二逼平衡树 树套树的主要内容,如果未能解决你的问题,请参考以下文章