bzoj 3196 树套树模板
Posted SD_le
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3196 树套树模板相关的知识,希望对你有一定的参考价值。
然而我还是在继续刷水题。。。
终于解开了区间第k大的心结。。。
比较裸的线段树套平衡树,比较不好想的是求区间第k大时需要二分一下答案,然后问题就转化为了第一个操作。复杂度nlog3n。跑的比较慢。。。
在查前驱后继的时候写错了。。。如果要直接赋值ans的话前驱是k[x]<=z,后继是k[x]<z,如果都写<的话需要取max和min。。。(不是第一次犯这种错了)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define lc x*2,l,mid 6 #define rc x*2+1,mid+1,r 7 #define ls(x) ch[x][0] 8 #define rs(x) ch[x][1] 9 #define inf 0x3f3f3f3f 10 using namespace std; 11 int n,m; 12 int root[50005*50]; 13 int size[50005*50],k[50005*50]; 14 int ch[50005*50][2],fa[50005*50]; 15 int a[50005]; 16 int cnt; 17 inline void push_up(int x) 18 { 19 size[x]=size[ch[x][0]]+size[ch[x][1]]+1; 20 return ; 21 } 22 inline void rotate(int p) 23 { 24 int q=fa[p],y=fa[q],x=(ch[q][1]==p); 25 ch[q][x]=ch[p][x^1];fa[ch[q][x]]=q; 26 ch[p][x^1]=q;fa[q]=p;fa[p]=y; 27 if(y) 28 { 29 if(ls(y)==q)ch[y][0]=p; 30 else ch[y][1]=p; 31 } 32 push_up(q);push_up(p); 33 } 34 inline void splay(int now,int x) 35 { 36 for(int y;y=fa[x];rotate(x)) 37 { 38 if(fa[y]) 39 { 40 if((ls(y)==x&&ls(fa[y])==y)||(rs(y)==x&&rs(fa[y])==y))rotate(y); 41 else rotate(x); 42 } 43 } 44 root[now]=x; 45 } 46 inline void insert(int now,int x,int z) 47 { 48 size[x]++; 49 while(ch[x][k[x]<z])x=ch[x][k[x]<z],size[x]++; 50 ch[x][k[x]<z]=++cnt;fa[cnt]=x;size[cnt]=1;k[cnt]=z;splay(now,cnt); 51 } 52 inline void build(int x,int l,int r) 53 { 54 root[x]=++cnt;k[cnt]=a[l];size[cnt]=1; 55 for(int i=l+1;i<=r;i++)insert(x,root[x],a[i]); 56 int mid=(l+r)>>1; 57 if(l<r)build(lc),build(rc); 58 return ; 59 } 60 inline int fd(int x,int z) 61 { 62 int ans=0; 63 while(x) 64 { 65 if(k[x]>z) 66 { 67 x=ch[x][0]; 68 } 69 else ans+=size[ch[x][0]]+1,x=ch[x][1]; 70 } 71 return ans; 72 } 73 inline int qur(int x,int l,int r,int ll,int rr,int kk) 74 { 75 if(ll<=l&&rr>=r) 76 { 77 return fd(root[x],kk); 78 } 79 int mid=(l+r)>>1; 80 int ans=0; 81 if(ll<=mid)ans+=qur(lc,ll,rr,kk); 82 if(rr>mid)ans+=qur(rc,ll,rr,kk); 83 return ans; 84 } 85 inline int find(int x,int z) 86 { 87 if(k[x]==z)return x; 88 while(ch[x][k[x]<z]) 89 { 90 x=ch[x][k[x]<z];if(k[x]==z)return x; 91 } 92 return 0; 93 } 94 inline void del(int now,int x) 95 { 96 splay(now,x); 97 if(!ch[x][0])root[now]=ch[x][1],fa[ch[x][1]]=0; 98 else if(!ch[x][1])root[now]=ch[x][0],fa[ch[x][0]]=0; 99 else 100 { 101 fa[ch[x][0]]=0;int tmp=ch[x][0]; 102 while(ch[tmp][1])tmp=ch[tmp][1]; 103 splay(now,tmp);ch[tmp][1]=ch[x][1];fa[ch[x][1]]=tmp;push_up(tmp); 104 } 105 } 106 inline void gai(int x,int l,int r,int pos,int z) 107 { 108 insert(x,root[x],z); 109 int x1=find(root[x],a[pos]); 110 del(x,x1); 111 if(l==r)return ; 112 int mid=(l+r)>>1; 113 if(pos<=mid)gai(lc,pos,z); 114 else gai(rc,pos,z); 115 } 116 inline int pre(int x,int z) 117 { 118 int ans=-inf; 119 while(ch[x][k[x]<=z]) 120 { 121 if(k[x]<=z)ans=k[x]; 122 x=ch[x][k[x]<=z]; 123 }if(k[x]<=z)ans=max(ans,k[x]); 124 return ans; 125 } 126 inline int suc(int x,int z) 127 { 128 int ans=inf; 129 while(ch[x][k[x]<z]) 130 { 131 if(k[x]>=z)ans=k[x]; 132 x=ch[x][k[x]<z]; 133 }if(k[x]>=z)ans=min(ans,k[x]); 134 return ans; 135 } 136 inline int qur_pre(int x,int l,int r,int ll,int rr,int kk) 137 { 138 if(l>=ll&&r<=rr) 139 { 140 return pre(root[x],kk); 141 } 142 int ans=-inf; 143 int mid=(l+r)>>1; 144 if(ll<=mid)ans=max(ans,qur_pre(lc,ll,rr,kk)); 145 if(rr>mid)ans=max(ans,qur_pre(rc,ll,rr,kk)); 146 return ans; 147 } 148 inline int qur_suc(int x,int l,int r,int ll,int rr,int kk) 149 { 150 if(l>=ll&&r<=rr) 151 { 152 return suc(root[x],kk); 153 } 154 int ans=inf; 155 int mid=(l+r)>>1; 156 if(ll<=mid)ans=min(ans,qur_suc(lc,ll,rr,kk)); 157 if(rr>mid)ans=min(ans,qur_suc(rc,ll,rr,kk)); 158 return ans; 159 } 160 int mn,mx; 161 int main() 162 { 163 scanf("%d%d",&n,&m);mn=inf;mx=-inf; 164 for(int i=1;i<=n;i++) 165 { 166 scanf("%d",&a[i]);mn=min(mn,a[i]);mx=max(mx,a[i]); 167 } 168 build(1,1,n); 169 for(int i=1;i<=m;i++) 170 { 171 int t1; 172 scanf("%d",&t1); 173 int l,r,kk; 174 if(t1==1) 175 { 176 scanf("%d%d%d",&l,&r,&kk); 177 printf("%d\n",qur(1,1,n,l,r,kk-1)+1); 178 } 179 else if(t1==2) 180 { 181 scanf("%d%d%d",&l,&r,&kk); 182 int ha=mn;int ta=mx; 183 while(ha<=ta) 184 { 185 int mid=(ha+ta)>>1; 186 if(qur(1,1,n,l,r,mid)<kk)ha=mid+1; 187 else ta=mid-1; 188 } 189 printf("%d\n",ha); 190 } 191 else if(t1==3) 192 { 193 scanf("%d%d",&l,&kk); 194 gai(1,1,n,l,kk);a[l]=kk; 195 } 196 else if(t1==4) 197 { 198 scanf("%d%d%d",&l,&r,&kk); 199 printf("%d\n",qur_pre(1,1,n,l,r,kk-1)); 200 } 201 else 202 { 203 scanf("%d%d%d",&l,&r,&kk); 204 printf("%d\n",qur_suc(1,1,n,l,r,kk+1)); 205 } 206 } 207 return 0; 208 }
以上是关于bzoj 3196 树套树模板的主要内容,如果未能解决你的问题,请参考以下文章