1. 程式人生 > >bzoj3196: Tyvj 1730 二逼平衡樹 樹套樹

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

con oid get clas val else include pda upd

地址: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 二逼平衡樹 樹套樹