BZOJ 3196 Tyvj 1730 二逼平衡树 树套树 线段树 treap
http://www.lydsy.com/JudgeOnline/problem.php?id=3196
线段树套treap,似乎splay也可以但是抄的hzwer学长的代码。。就写了treap,算是比较需要注意细节的题。需要注意的地方都在注释里。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<cstdlib> 7 #include<cctype> 8 using namespace std; 9 #define lc 2*x 10 #define rc 2*x+1 11 const int maxn=50010; 12 const int inf=100000000; 13 int n,m; 14 int root[maxn*4]; 15 struct tre{ 16 int v,ls,rs,w; 17 int rd,siz; 18 }t[maxn*40]; 19 struct seg{ 20 int l,r,mid; 21 }e[maxn*4]; 22 int a[maxn]={},tot=0,ans; 23 int read(){ 24 int x=0,f=1;char ch=getchar(); 25 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 26 while(isdigit(ch)){x*=10;x+=ch-'0';ch=getchar();} 27 return x*f; 28 } 29 inline void update(int x){t[x].siz=t[t[x].ls].siz+t[t[x].rs].siz+t[x].w;} 30 inline void rturn(int &x){//左儿子成为根 31 int y=t[x].ls; 32 t[x].ls=t[y].rs; t[y].rs=x; 33 update(x); x=y; 34 } 35 inline void lturn(int &x){//右儿子成为根 36 int y=t[x].rs; 37 t[x].rs=t[y].ls; t[y].ls=x; 38 update(x); x=y; 39 } 40 void insert(int &x,int v){//把一个值放进去 41 if(!x){x=++tot;t[x].siz=t[x].w=1;t[x].v=v;t[x].rd=rand();return;} 42 t[x].siz++; 43 if(t[x].v==v)t[x].w++; 44 else if(v<t[x].v){ insert(t[x].ls,v);if(t[x].rd>t[t[x].ls].rd)rturn(x);} 45 else {insert(t[x].rs,v);if(t[x].rd>t[t[x].rs].rd)lturn(x);} 46 update(x); 47 } 48 void del(int &x,int v){//把一个值去掉 49 if(t[x].v==v){ 50 if(t[x].w>1){t[x].w--;t[x].siz--;return;} 51 if(t[x].ls*t[x].rs==0)x=t[x].ls+t[x].rs;//使该位置成为其儿子 52 else if(t[t[x].ls].rd<t[t[x].rs].rd){rturn(x);del(t[x].rs,v);} 53 //我觉得此时delx是没有必要的可以直接delx的儿子,标注出来如果ac不了再改回去。 54 else {lturn(x);del(t[x].ls,v);} 55 } 56 else if(v<t[x].v)del(t[x].ls,v); 57 else del(t[x].rs,v); 58 update(x); 59 } 60 void build(int x,int l,int r){//线段树结构 61 for(int i=l;i<=r;i++)insert(root[x],a[i]); 62 e[x].l=l;e[x].r=r; 63 if(l==r)return; 64 int mid=(l+r)/2;e[x].mid=mid; 65 build(lc,l,mid); 66 build(rc,mid+1,r); 67 } 68 int getrank2(int x,int v){ 69 if(!x)return 0; 70 if(t[x].v==v)return t[t[x].ls].siz; 71 else if(t[x].v>v)return getrank2(t[x].ls,v); 72 else return t[t[x].ls].siz+t[x].w+getrank2(t[x].rs,v); 73 } 74 int getrank(int x,int l,int r,int v){//线段树结构 75 if(l<=e[x].l&&r>=e[x].r){ 76 return getrank2(root[x],v); 77 }int pai=0; 78 if(l<=e[x].mid)pai+=getrank(lc,l,r,v); 79 if(e[x].mid<r)pai+=getrank(rc,l,r,v); 80 return pai; 81 } 82 void getnum(int x,int y,int k){//二分 83 int l=0,r=inf,cnt=0; 84 while(l<=r){//注意二分答案的储存方法,如何避免取到不存在的值 85 int mid=(l+r)/2; 86 int w=getrank(1,x,y,mid)+1; 87 if(w<=k){l=mid+1;cnt=mid;} 88 else r=mid-1; 89 }printf("%d\n",cnt); 90 } 91 void change(int x,int z,int v){//线段树结构 92 del(root[x],a[z]); 93 insert(root[x],v); 94 if(e[x].l==e[x].r)return; 95 if(z<=e[x].mid)change(lc,z,v); 96 else change(rc,z,v); 97 } 98 void befo(int x,int num){ 99 if(!x)return; 100 if(t[x].v<num){ans=max(t[x].v,ans);befo(t[x].rs,num);} 101 else befo(t[x].ls,num); 102 } 103 void afte(int x,int num){ 104 if(!x)return; 105 if(t[x].v>num){ans=min(t[x].v,ans);afte(t[x].ls,num);} 106 else afte(t[x].rs,num); 107 } 108 void fir(int x,int l,int r,int num){//线段树结构 109 if(l<=e[x].l&&e[x].r<=r){ 110 befo(root[x],num); 111 return; 112 } 113 if(l<=e[x].mid)fir(lc,l,r,num); 114 if(e[x].mid<r)fir(rc,l,r,num); 115 } 116 void las(int x,int l,int r,int num){//线段树结构 117 if(l<=e[x].l&&e[x].r<=r){ 118 afte(root[x],num); 119 return; 120 } 121 if(l<=e[x].mid)las(lc,l,r,num); 122 if(e[x].mid<r)las(rc,l,r,num); 123 } 124 int main(){ 125 //freopen("wtf.in","r",stdin); 126 n=read();m=read(); 127 for(int i=1;i<=n;i++)a[i]=read(); 128 build(1,1,n);int x,y,z,f; 129 for(int i=1;i<=m;i++){ 130 scanf("%d",&f); 131 if(f==1){scanf("%d%d%d",&x,&y,&z);printf("%d\n",getrank(1,x,y,z)+1);} 132 else if(f==2){scanf("%d%d%d",&x,&y,&z);getnum(x,y,z);} 133 else if(f==3){scanf("%d%d",&x,&y);change(1,x,y);a[x]=y;}//记得把数组也改了。。一直re,大概因为这样导致del出现不存在的数无限递归 134 else if(f==4){scanf("%d%d%d",&x,&y,&z);ans=0;fir(1,x,y,z);printf("%d\n",ans);} 135 else{scanf("%d%d%d",&x,&y,&z);ans=inf;las(1,x,y,z);printf("%d\n",ans);} 136 } 137 return 0; 138 }