Splay(区间翻转)&树套树(Splay+线段树,90分)

study from:

https://tiger0132.blog.luogu.org/slay-notes

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 #define ll long long
 10 
 11 const double eps=1e-8;
 12 const ll inf=1e9;
 13 const ll mod=1e9+7;
 14 const int maxn=1e5+10;
 15 
 16 int par[maxn],son[maxn][2],siz[maxn],val[maxn],cnt[maxn],root,id;
 17 
 18 int chk(int x)
 19 {
 20     return son[par[x]][1]==x;
 21 }
 22 
 23 void pushup(int x)
 24 {
 25     siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
 26 }
 27 
 28 void rotate(int x)
 29 {
 30     int y=par[x];
 31     int z=par[y];
 32     int k=chk(x);
 33     int w=son[x][k^1];
 34     son[y][k]=w,par[w]=y;
 35     son[z][chk(y)]=x,par[x]=z;
 36     son[x][k^1]=y,par[y]=x;
 37     pushup(y),pushup(x);
 38 }
 39 
 40 void splay(int x,int goal=0)
 41 {
 42     int y,z;
 43     while (par[x]!=goal)
 44     {
 45         y=par[x];
 46         z=par[y];
 47         if (z!=goal)
 48         {
 49             if (chk(x)==chk(y))
 50                 rotate(y);
 51             else
 52                 rotate(x);
 53         }
 54         rotate(x);
 55     }
 56     if (!goal)
 57         root=x;
 58 }
 59 
 60 void find(int x)
 61 {
 62     if (!root)
 63         return;
 64     int cur=root;
 65     while (son[cur][x>val[cur]] && x!=val[cur])
 66         cur=son[cur][x>val[cur]];
 67     splay(cur); ///用于找到排名,前继,后继
 68 }
 69 
 70 void insert(int x)
 71 {
 72     int cur=root,p=0;
 73     while (cur && val[cur]!=x)
 74     {
 75         p=cur;
 76         cur=son[cur][x>val[cur]];
 77     }
 78     if (cur)
 79         cnt[cur]++;
 80     else
 81     {
 82         cur=++id;
 83         if (p)
 84         {
 85             son[p][x>val[p]]=cur;
 86             siz[p]++;   ///不写也行,在splay(cur)中会更改
 87         }
 88         son[cur][0]=son[cur][1]=0;
 89         val[cur]=x;
 90         par[cur]=p;
 91         cnt[cur]=siz[cur]=1;
 92     }
 93     splay(cur); ///保持平衡
 94 }
 95 
 96 int kth(int k)
 97 {
 98     int cur=root;
 99     while (1)
100     {
101         if (son[cur][0] && k<=siz[son[cur][0]])
102             cur=son[cur][0];
103         else if (k>siz[son[cur][0]]+cnt[cur])
104         {
105             k-=siz[son[cur][0]]+cnt[cur];
106             cur=son[cur][1];
107         }
108         else
109             return cur;
110     }
111 }
112 
113 void x_rank(int x)
114 {
115     find(x);
116     if (val[root]>=x)   ///根节点所在的值不选用
117         printf("%d
",siz[son[root][0]]+1-1); ///最小的点
118     else
119         printf("%d
",siz[son[root][0]]+cnt[root]+1-1);   ///最小的点
120 }
121 
122 int pre(int x)
123 {
124     find(x);
125     if (val[root]<x)
126         return root;
127     int cur=son[root][0];
128     while (son[cur][1])
129         cur=son[cur][1];
130     return cur;
131 }
132 
133 int succ(int x)
134 {
135     find(x);
136     if (val[root]>x)
137         return root;
138     int cur=son[root][1];
139     while (son[cur][0])
140         cur=son[cur][0];
141     return cur;
142 }
143 
144 void remove(int x)
145 {
146     int last=pre(x);
147     int next=succ(x);
148     splay(last);
149     splay(next,last);
150     int del=son[next][0];   ///有且只有一个节点
151     if (cnt[del]>1)
152     {
153         cnt[del]--;
154         splay(del);
155     }
156     else
157         son[next][0]=0; ///删除该节点
158     pushup(next),pushup(root);
159 }
160 
161 int main()
162 {
163     int t,mode,x;
164 insert(0xefefefef); ///增加最小的点,pre也许不存在 165 insert(0x3f3f3f3f); ///增加最大的点,succ也许不存在 166 scanf("%d",&t); 167 while (t--) 168 { 169 scanf("%d%d",&mode,&x); 170 if (mode==1) 171 insert(x); 172 else if (mode==2) 173 remove(x); 174 else if (mode==3) 175 x_rank(x); 176 else if (mode==4) 177 printf("%d ",val[kth(x+1)]); ///最小的点 178 else if (mode==5) 179 printf("%d ",val[pre(x)]); 180 else if (mode==6) 181 printf("%d ",val[succ(x)]); 182 } 183 return 0; 184 }

考虑到刚访问的节点在之后有可能很快将再次访问

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 #define ll long long
 10 
 11 const double eps=1e-8;
 12 const ll inf=1e9;
 13 const ll mod=1e9+7;
 14 const int maxn=1e5+10;
 15 
 16 int par[maxn],son[maxn][2],siz[maxn],val[maxn],cnt[maxn],root,id;
 17 
 18 int chk(int x)
 19 {
 20     return son[par[x]][1]==x;
 21 }
 22 
 23 void pushup(int x)
 24 {
 25     siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
 26 }
 27 
 28 void rotate(int x)
 29 {
 30     int y=par[x];
 31     int z=par[y];
 32     int k=chk(x);
 33     int w=son[x][k^1];
 34     son[y][k]=w,par[w]=y;
 35     son[z][chk(y)]=x,par[x]=z;
 36     son[x][k^1]=y,par[y]=x;
 37     pushup(y),pushup(x);
 38 }
 39 
 40 void splay(int x,int goal=0)
 41 {
 42     int y,z;
 43     while (par[x]!=goal)
 44     {
 45         y=par[x];
 46         z=par[y];
 47         if (z!=goal)
 48         {
 49             if (chk(x)==chk(y))
 50                 rotate(y);
 51             else
 52                 rotate(x);
 53         }
 54         rotate(x);
 55     }
 56     if (!goal)
 57         root=x;
 58 }
 59 
 60 void find(int x)
 61 {
 62     if (!root)
 63         return;
 64     int cur=root;
 65     while (son[cur][x>val[cur]] && x!=val[cur])
 66         cur=son[cur][x>val[cur]];
 67     splay(cur);
 68 }
 69 
 70 void insert(int x)
 71 {
 72     int cur=root,p=0;
 73     while (cur && val[cur]!=x)
 74     {
 75         p=cur;
 76         cur=son[cur][x>val[cur]];
 77     }
 78     if (cur)
 79         cnt[cur]++;
 80     else
 81     {
 82         cur=++id;
 83         if (p)
 84             son[p][x>val[p]]=cur;
 85         son[cur][0]=son[cur][1]=0;
 86         val[cur]=x;
 87         par[cur]=p;
 88         cnt[cur]=siz[cur]=1;
 89     }
 90     splay(cur);
 91 }
 92 
 93 int kth(int k)
 94 {
 95     int cur=root;
 96     while (1)
 97     {
 98         if (son[cur][0] && k<=siz[son[cur][0]])
 99             cur=son[cur][0];
100         else if (k>siz[son[cur][0]]+cnt[cur])
101         {
102             k-=siz[son[cur][0]]+cnt[cur];
103             cur=son[cur][1];
104         }
105         else
106         {
107             splay(cur);
108             return cur;
109         }
110     }
111 }
112 
113 void x_rank(int x)
114 {
115     find(x);
116     if (val[root]>=x)   ///根节点所在的值不选用
117         printf("%d
",siz[son[root][0]]+1-1); ///最小的点
118     else
119         printf("%d
",siz[son[root][0]]+cnt[root]+1-1);   ///最小的点
120 }
121 
122 int pre(int x)
123 {
124     find(x);
125     if (val[root]<x)
126         return root;
127     int cur=son[root][0];
128     while (son[cur][1])
129         cur=son[cur][1];
130     splay(cur);
131     return cur;
132 }
133 
134 int succ(int x)
135 {
136     find(x);
137     if (val[root]>x)
138         return root;
139     int cur=son[root][1];
140     while (son[cur][0])
141         cur=son[cur][0];
142     splay(cur);
143     return cur;
144 }
145 
146 void remove(int x)
147 {
148     int last=pre(x);
149     int next=succ(x);
150     splay(last);
151     splay(next,last);
152     int del=son[next][0];   ///有且只有一个节点
153     if (cnt[del]>1)
154     {
155         cnt[del]--;
156         splay(del);
157     }
158     else
159         son[next][0]=0; ///删除该节点
160     pushup(next),pushup(root);
161 }
162 
163 int main()
164 {
165     int t,mode,x;
166     insert(0x3f3f3f3f);
167     insert(0xefefefef);
168     scanf("%d",&t);
169     while (t--)
170     {
171         scanf("%d%d",&mode,&x);
172         if (mode==1)
173             insert(x);
174         else if (mode==2)
175             remove(x);
176         else if (mode==3)
177             x_rank(x);
178         else if (mode==4)
179             printf("%d
",val[kth(x+1)]);   ///最小的点
180         else if (mode==5)
181             printf("%d
",val[pre(x)]);
182         else if (mode==6)
183             printf("%d
",val[succ(x)]);
184     }
185     return 0;
186 }

一些想法和其它的写法

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 #define ll long long
 10 
 11 const double eps=1e-8;
 12 const ll inf=1e9;
 13 const ll mod=1e9+7;
 14 const int maxn=1e5+10;
 15 
 16 int par[maxn],son[maxn][2],siz[maxn],val[maxn],cnt[maxn],root,id;
 17 
 18 int max_op;
 19 
 20 int chk(int x)
 21 {
 22     return son[par[x]][1]==x;
 23 }
 24 
 25 void pushup(int x)
 26 {
 27     siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
 28 }
 29 
 30 void rotate(int x)
 31 {
 32     int y=par[x];
 33     int z=par[y];
 34     int k=chk(x);
 35     int w=son[x][k^1];
 36     son[y][k]=w,par[w]=y;
 37     son[z][chk(y)]=x,par[x]=z;
 38     son[x][k^1]=y,par[y]=x;
 39     pushup(y),pushup(x);
 40 }
 41 
 42 void splay(int x,int goal=0)
 43 {
 44     int y,z;
 45     while (par[x]!=goal)
 46     {
 47         y=par[x];
 48         z=par[y];
 49         if (z!=goal)
 50         {
 51             if (chk(x)==chk(y))
 52                 rotate(y);
 53             else
 54                 rotate(x);
 55         }
 56         rotate(x);
 57     }
 58     if (!goal)
 59         root=x;
 60 }
 61 
 62 void find(int x)
 63 {
 64     if (!root)
 65         return;
 66     int cur=root;
 67     while (son[cur][x>val[cur]] && x!=val[cur])
 68         cur=son[cur][x>val[cur]];
 69     splay(cur); ///用于找到排名,前继,后继
 70 }
 71 
 72 void insert(int x)
 73 {
 74     int cur=root,p=0;
 75     while (cur && val[cur]!=x)
 76     {
 77         p=cur;
 78         cur=son[cur][x>val[cur]];
 79     }
 80     if (cur)
 81         cnt[cur]++;
 82     else
 83     {
 84         cur=++id;
 85         if (p)
 86         {
 87             son[p][x>val[p]]=cur;
 88             siz[p]++;   ///不写也行,在splay(cur)中会更改
 89         }
 90         son[cur][0]=son[cur][1]=0;
 91         val[cur]=x;
 92         par[cur]=p;
 93         cnt[cur]=siz[cur]=1;
 94     }
 95     splay(cur); ///保持平衡
 96 }
 97 
 98 int kth(int k)
 99 {
100     int cur=root;
101     while (1)
102     {
103         if (son[cur][0] && k<=siz[son[cur][0]])
104             cur=son[cur][0];
105         else if (k>siz[son[cur][0]]+cnt[cur])
106         {
107             k-=siz[son[cur][0]]+cnt[cur];
108             cur=son[cur][1];
109         }
110         else
111             return cur;
112     }
113 }
114 
115 int x_rank(int x)
116 {
117     find(x); ///比x小的数目 +1
118     if (val[root]>=x)   ///根节点所在的值不选用
119         return siz[son[root][0]]+1; ///最小的点
120     else
121         return siz[son[root][0]]+cnt[root]+1;   ///最小的点
122 }
123 
124 /**
125 超时
126 max_op=49999
127 
128 下方的
129 1 1
130 1 2
131 1 3
132 ...
133 的读入方式,会使产生一条长长的链
134 
135 
136 求深度大的点,
137 splay操作,
138 会使深度趋于平衡。
139 
140 在这里没有splay操作,
141 每次处理的都是长链
142 **/
143 //int x_rank(int x)
144 //{
145 //    int op=0;
146 //    int cur=root,sum=0;
147 //    while (!(son[cur][0]==0 && son[cur][1]==0) && val[cur]!=x)
148 //    {
149 //        if (x<val[cur])
150 //            cur=son[cur][0];
151 //        else
152 //        {
153 //            sum+=siz[son[cur][0]]+cnt[cur];
154 //            cur=son[cur][1];
155 //        }
156 //        op++;
157 //    }
158 //    max_op=max(max_op,op);
159 //    return sum+siz[son[cur][0]]+1;
160 //}
161 
162 int pre(int x)
163 {
164     find(x);
165     if (val[root]<x)
166         return root;
167     int cur=son[root][0];
168     while (son[cur][1])
169         cur=son[cur][1];
170     return cur;
171 }
172 
173 ///also ok
174 //int pre(int x)
175 //{
176 //    int num=x_rank(x);///里面包含find函数
177 //    return kth(num-1);
178 //}
179 
180 int succ(int x)
181 {
182     find(x);
183     if (val[root]>x)
184         return root;
185     int cur=son[root][1];
186     while (son[cur][0])
187         cur=son[cur][0];
188     return cur;
189 }
190 
191 ///also ok
192 //int succ(int x)
193 //{
194 //    int num=x_rank(x);
195 //    if (val[root]==x)
196 //        return kth(num+cnt[root]);
197 //    else
198 //        return kth(num);
199 //}
200 
201 void remove(int x)
202 {
203     int last=pre(x);
204     int next=succ(x);
205     splay(last);
206     splay(next,last);
207     int del=son[next][0];   ///有且只有一个节点
208     if (cnt[del]>1)
209     {
210         cnt[del]--;
211         splay(del);
212     }
213     else
214         son[next][0]=0; ///删除该节点
215     pushup(next),pushup(root);
216 }
217 
218 int main()
219 {
220     int t,mode,x;
221     insert(0xefefefef); ///增加最小的点,pre也许不存在
222     insert(0x3f3f3f3f); ///增加最大的点,succ也许不存在
223     scanf("%d",&t);
224     while (t--)
225     {
226         scanf("%d%d",&mode,&x);
227         if (mode==1)
228             insert(x);
229         else if (mode==2)
230             remove(x);
231         else if (mode==3)
232             printf("%d
",x_rank(x)-1);
233         else if (mode==4)
234             printf("%d
",val[kth(x+1)]);   ///最小的点
235         else if (mode==5)
236             printf("%d
",val[pre(x)]);
237         else if (mode==6)
238             printf("%d
",val[succ(x)]);
239     }
240 
241 //    printf("max_op=%d",max_op);
242     return 0;
243 }
244 /*
245 4
246 1 1
247 3 1
248 5 1
249 6 1
250 
251 
252 100
253 1 1
254 1 2
255 1 3
256 1 4
257 1 5
258 1 6
259 1 7
260 1 8
261 1 9
262 1 10
263 3 1
264 3 10
265 */

P3391 【模板】文艺平衡树(Splay)

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 #define ll long long
 10 
 11 const double eps=1e-8;
 12 const ll inf=1e9;
 13 const ll mod=1e9+7;
 14 const int maxn=1e5+10;
 15 
 16 int vir1=0xefefefef,vir2=0x3f3f3f3f;
 17 int par[maxn],son[maxn][2],val[maxn],siz[maxn],rev[maxn],id,root,n;
 18 bool pr;
 19 
 20 int chk(int x)
 21 {
 22     return son[par[x]][1]==x;
 23 }
 24 
 25 void pushup(int x)
 26 {
 27     siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
 28 }
 29 
 30 void rotate(int x)
 31 {
 32     int y=par[x];
 33     int z=par[y];
 34     int k=chk(x);
 35     int w=son[x][k^1];
 36     son[y][k]=w,par[w]=y;
 37     son[z][chk(y)]=x,par[x]=z;
 38     son[x][k^1]=y,par[y]=x;
 39     pushup(y),pushup(x);
 40 }
 41 
 42 void splay(int x,int goal=0)
 43 {
 44     int y,z;
 45     while (par[x]!=goal)
 46     {
 47         y=par[x];
 48         z=par[y];
 49         if (z!=goal)
 50         {
 51             if (chk(x)==chk(y))
 52                 rotate(y);
 53             else
 54                 rotate(x);
 55         }
 56         rotate(x);
 57     }
 58     if (!goal)
 59         root=x;
 60 }
 61 
 62 ///编号从小到大,当前编号比之前读入的数的编号大
 63 void insert(int x)    ///数值
 64 {
 65     int cur=root,p=0;
 66     while (cur)
 67     {
 68         p=cur;
 69         cur=son[cur][1];
 70     }
 71 
 72     cur=++id;
 73     if (p)
 74     {
 75         son[p][1]=cur;
 76         siz[p]++;
 77     }
 78     son[cur][0]=son[cur][1]=0;
 79     par[cur]=p;
 80     val[cur]=x;
 81     siz[cur]=1;
 82     splay(cur);
 83 }
 84 
 85 void pushdown(int x)
 86 {
 87     if (rev[x])
 88     {
 89         swap(son[x][0],son[x][1]);
 90         rev[son[x][0]]^=1;
 91         rev[son[x][1]]^=1;
 92         rev[x]=0;
 93     }
 94 }
 95 
 96 int kth(int k)
 97 {
 98     int cur=root;
 99     while (1)
100     {
101         pushdown(cur);
102         if (son[cur][0] && k<=siz[son[cur][0]])
103             cur=son[cur][0];
104         else if (k>siz[son[cur][0]]+1)
105         {
106             k-=siz[son[cur][0]]+1;
107             cur=son[cur][1];
108         }
109         else
110             return cur;
111     }
112 }
113 
114 void reverse(int l,int r)
115 {
116     int x=kth(l-1),y=kth(r+1);
117     splay(x);
118     splay(y,x);
119     rev[son[y][0]]^=1;  ///interval [l,r], between l-1 and r+1
120 }
121 
122 void print(int x)
123 {
124     pushdown(x);
125     if (son[x][0])
126         print(son[x][0]);
127     if (x!=1 && x!=n+2) ///smallest and largest number
128     {
129         if (!pr)
130             pr=1;
131         else
132             printf(" ");
133         printf("%d",val[x]);
134     }
135     if (son[x][1])
136         print(son[x][1]);
137 }
138 
139 int main()
140 {
141     int t,i,x,y;
142     scanf("%d%d",&n,&t);
143     insert(vir1);   ///smallest number, for l-1
144     for (i=1;i<=n;i++)
145         insert(i);
146     insert(vir2);   ///largest number, for r+1
147     while (t--)
148     {
149         scanf("%d%d",&x,&y);
150         reverse(x+1,y+1);   ///contain virtual smallest number
151     }
152     print(root);
153     return 0;
154 }
155 /*
156 5 0
157 
158 5 1
159 1 5
160 */

P2042 [NOI2005]维护数列

见 https://tiger0132.blog.luogu.org/slay-notes

P3380 【模板】二逼平衡树(树套树)

线段树套Splay

每个线段树的点区间有一个Splay。

每个点(a[1]~a[n])在log(n)个线段树的点区间中。

动态开点。

相比动态主席树的优势:

空间nlogn

时间复杂度:

参见https://www.cnblogs.com/LadyLex/p/8006478.html,讲得挺好

(图片来自https://www.cnblogs.com/LadyLex/p/8006478.html)

(图片来自https://www.luogu.org/problemnew/solution/P3380)

既然是区间第k大的时间复杂度是

log(n)*log(n)*log(value_range),

那么肯定会超时才对啊……

只有其它方法才能过……

或者是实际跑起来,远没有到达理论的时间复杂度……

估计是数据没有造到极限,

而我的代码常数太高了……

原来开O2优化(提交时选择)……

需要添加

#pragma GCC optimize(2)

调试时去掉这句话

否则有些变量显示optimized out,无法看到数值

也许更快的方法:

zkw线段树,树状数组

90分

求kth,记录修改的位置,之后不用每次求修改的位置(都是一样的)

  1 #pragma GCC optimize(2)
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <cstring>
  6 #include <string>
  7 #include <algorithm>
  8 #include <iostream>
  9 using namespace std;
 10 #define ll long long
 11 
 12 /**
 13 log(n)=16
 14 n*log(n)*log(n)=12800000
 15 **/
 16 
 17 const double eps=1e-8;
 18 const ll mod=1e9+7;
 19 const int maxn=5e4+10;
 20 const int maxf=maxn<<2;
 21 const int maxg=maxn*18+maxf*2;
 22 ///n * log(n)[larger] (每个点在log(n)个区间中出现) + 每个区间加上两个虚拟点(最小、最大)
 23 
 24 struct node
 25 {
 26     int l,r,b;
 27 }f[maxf];
 28 
 29 int par[maxg],son[maxg][2],val[maxg],cnt[maxg],siz[maxg];
 30 int a[maxn],id;
 31 int minv=0,maxv=1e8,vir1=-2147483647,vir2=2147483647;
 32 int cal_num[maxn],cnt_cal_num;
 33 
 34 int chk(int x)
 35 {
 36     return son[par[x]][1]==x;
 37 }
 38 
 39 void pushup(int x)
 40 {
 41     siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
 42 }
 43 
 44 void rotate(int x)
 45 {
 46     int y=par[x];
 47     int z=par[y];
 48     int k=chk(x);
 49     int w=son[x][k^1];
 50     son[y][k]=w,par[w]=y;
 51     son[z][chk(y)]=x,par[x]=z;
 52     son[x][k^1]=y,par[y]=x;
 53     pushup(y),pushup(x);
 54 }
 55 
 56 void splay(int &root,int x,int goal=0)
 57 {
 58     int y,z;
 59     while (par[x]!=goal)
 60     {
 61         y=par[x];
 62         z=par[y];
 63         if (z!=goal)
 64         {
 65             if (chk(x)==chk(y))
 66                 rotate(y);
 67             else
 68                 rotate(x);
 69         }
 70         rotate(x);
 71     }
 72     if (!goal)
 73         root=x;
 74 }
 75 
 76 void find(int &root,int x)
 77 {
 78     if (!root)
 79         return;
 80     int cur=root;
 81     while (son[cur][x>val[cur]] && x!=val[cur])
 82         cur=son[cur][x>val[cur]];
 83     splay(root,cur);
 84 }
 85 
 86 int pre(int &root,int x)
 87 {
 88     find(root,x);
 89     if (val[root]<x)
 90         return root;
 91     int cur=son[root][0];
 92     while (son[cur][1])
 93         cur=son[cur][1];
 94     return cur;
 95 }
 96 
 97 int succ(int &root,int x)
 98 {
 99     find(root,x);
100     if (val[root]>x)
101         return root;
102     int cur=son[root][1];
103     while (son[cur][0])
104         cur=son[cur][0];
105     return cur;
106 }
107 
108 void insert(int &root,int x)
109 {
110     int cur=root,p=0;
111     while (cur && val[cur]!=x)
112     {
113         p=cur;
114         cur=son[cur][x>val[cur]];
115     }
116     if (cur)
117         cnt[cur]++;
118     else
119     {
120         cur=++id;
121         if (p)
122         {
123             son[p][x>val[p]]=cur;
124             siz[p]++;
125         }
126         son[cur][0]=son[cur][1]=0;
127         val[cur]=x;
128         par[cur]=p;
129         cnt[cur]=siz[cur]=1;
130     }
131     splay(root,cur);
132 }
133 
134 void remove(int &root,int x)
135 {
136     int last=pre(root,x);
137     int next=succ(root,x);
138     splay(root,last);
139     splay(root,next,last);
140     int del=son[next][0];
141     if (cnt[del]>1)
142     {
143         cnt[del]--;
144         splay(root,del);
145     }
146     else
147         son[next][0]=0;
148     pushup(next),pushup(root);
149 }
150 
151 //int kth(int &root,int k)
152 //{
153 //    int cur=root;
154 //    while (1)
155 //    {
156 //        if (son[cur][0] && k<=siz[son[cur][0]])
157 //            cur=son[cur][0];
158 //        else if (k>siz[son[cur][0]]+cnt[cur])
159 //        {
160 //            k-=siz[son[cur][0]]+cnt[cur];
161 //            cur=son[cur][1];
162 //        }
163 //        else
164 //            return cur;
165 //    }
166 //}
167 
168 int x_rank(int &root,int x)
169 {
170     find(root,x);
171     if (val[root]>=x)
172         return siz[son[root][0]];
173     else
174         return siz[son[root][0]]+cnt[root];
175 }
176 
177 void seg_insert(int ind,int l,int r,int x,int y)
178 {
179     ///也可以build()函数,初始化
180     if (!f[ind].b)
181     {
182         insert(f[ind].b,vir1);  ///根节点编号为0
183         f[ind].b=id;    ///根节点编号为id
184         insert(f[ind].b,vir2);
185     }
186     insert(f[ind].b,y);
187     if (l==r)
188         return;
189     int m=(l+r)>>1;
190     if (x<=m)
191         seg_insert(ind<<1,l,m,x,y);
192     else
193         seg_insert(ind<<1|1,m+1,r,x,y);
194 }
195 
196 void seg_remove(int ind,int l,int r,int x,int y)
197 {
198     remove(f[ind].b,y);
199     if (l==r)
200         return;
201     int m=(l+r)>>1;
202     if (x<=m)
203         seg_remove(ind<<1,l,m,x,y);
204     else
205         seg_remove(ind<<1|1,m+1,r,x,y);
206 }
207 
208 void cal_query_rank(int ind,int l,int r,int x,int y)
209 {
210     if (x<=l && r<=y)
211     {
212         cal_num[++cnt_cal_num]=ind;
213         return;
214     }
215     int m=(l+r)>>1;
216     if (x<=m)
217         cal_query_rank(ind<<1,l,m,x,y);
218     if (m<y)
219         cal_query_rank(ind<<1|1,m+1,r,x,y);
220 }
221 
222 int query_rank(int ind,int l,int r,int x,int y,int z)
223 {
224     if (x<=l && r<=y)
225         return x_rank(f[ind].b,z)-1;    ///减去最小虚拟点
226 
227     int m=(l+r)>>1,sum=0;
228     if (x<=m)
229         sum+=query_rank(ind<<1,l,m,x,y,z);
230     if (m<y)
231         sum+=query_rank(ind<<1|1,m+1,r,x,y,z);
232     return sum;
233 }
234 
235 int query_pre(int ind,int l,int r,int x,int y,int z)
236 {
237     if (x<=l && r<=y)
238         return val[pre(f[ind].b,z)];
239     int m=(l+r)>>1,re=vir1;
240     if (x<=m)
241         re=max(re,query_pre(ind<<1,l,m,x,y,z));
242     if (m<y)
243         re=max(re,query_pre(ind<<1|1,m+1,r,x,y,z));
244     return re;
245 }
246 
247 int query_succ(int ind,int l,int r,int x,int y,int z)
248 {
249     if (x<=l && r<=y)
250         return val[succ(f[ind].b,z)];
251     int m=(l+r)>>1,re=vir2;
252     if (x<=m)
253         re=min(re,query_succ(ind<<1,l,m,x,y,z));
254     if (m<y)
255         re=min(re,query_succ(ind<<1|1,m+1,r,x,y,z));
256     return re;
257 }
258 
259 int main()
260 {
261     int n,m,i,l,r,k,mode,x,L,R,mid;
262     scanf("%d%d",&n,&m);
263     for (i=1;i<=n;i++)
264     {
265         scanf("%d",&x);
266         seg_insert(1,1,n,i,x);
267         a[i]=x;
268     }
269     for (int M=1;M<=m;M++)
270     {
271         scanf("%d",&mode);
272         if (mode==3)
273             scanf("%d%d",&l,&k);
274         else
275             scanf("%d%d%d",&l,&r,&k);
276         if (mode==1)
277             ///log(n)*log(n)
278             printf("%d
",query_rank(1,1,n,l,r,k)+1);   ///比其小的点的数目+1
279         else if (mode==2)
280         {
281             ///log(value_range[maxv-minv])
282             ///可离散化成log(maxn+maxm),但写起来很复杂
283             ///可记录区间的最小、最大值,但写起来很麻烦,特别是涉及了数字修改
284 
285             ///每次遍历的内容都是一致的,用cal_query_rank函数记录下来
286 
287             cnt_cal_num=0;
288             cal_query_rank(1,1,n,l,r);
289 
290             L=minv,R=maxv;
291             while (L<=R)
292             {
293                 mid=(L+R)>>1;
294 
295                 x=1;
296                 for (i=1;i<=cnt_cal_num;i++)
297                     x+=x_rank(f[cal_num[i]].b,mid)-1;   ///f[index].b 会变化
298 
299                 ///log(n)*log(n)
300 //                x=query_rank(1,1,n,l,r,mid)+1;    ///
301                 if (x<=k)
302                     L=mid+1;
303                 else
304                     R=mid-1;
305             }
306             printf("%d
",R);
307         }
308         else if (mode==3)
309         {
310             ///log(n)*log(n)
311             seg_remove(1,1,n,l,a[l]);
312             ///log(n)*log(n)
313             seg_insert(1,1,n,l,k);
314             a[l]=k;
315         }
316         else if (mode==4)
317             ///log(n)*log(n)
318             printf("%d
",query_pre(1,1,n,l,r,k));
319         else
320             ///log(n)*log(n)
321             printf("%d
",query_succ(1,1,n,l,r,k));
322     }
323     return 0;
324 }
325 /*
326 9 100
327 4 2 2 1 9 4 0 1 1
328 
329 1 1 5 1
330 1 1 5 2
331 1 1 5 3
332 1 1 5 4
333 1 1 5 5
334 
335 2 1 5 1
336 2 1 5 2
337 2 1 5 3
338 2 1 5 4
339 2 1 5 5
340 
341 3 3 0
342 1 1 5 3
343 3 3 1
344 1 1 5 3
345 3 3 2
346 1 1 5 3
347 3 3 3
348 1 1 5 3
349 3 3 5
350 1 1 5 3
351 3 3 10
352 1 1 5 3
353 3 3 2
354 
355 4 1 5 0
356 4 1 5 1
357 4 1 5 2
358 4 1 5 3
359 4 1 5 4
360 4 1 5 5
361 
362 5 1 5 0
363 5 1 5 1
364 5 1 5 2
365 5 1 5 3
366 5 1 5 4
367 5 1 5 9
368 5 1 5 10
369 
370 
371 9 100
372 1 1 1 1 1 1 1 1 1
373 1 1 10 1
374 1 1 10 10
375 1 1 10 5
376 2 1 10 1
377 2 1 10 9
378 2 1 10 5
379 4 1 10 1
380 4 1 10 5
381 5 1 10 1
382 5 1 10 -5
383 
384 
385 5 100
386 1 2 3 2 1
387 2 1 5 1
388 2 1 5 2
389 2 1 5 3
390 2 1 5 4
391 2 1 5 5
392 2 2 5 1
393 2 2 5 2
394 2 2 5 3
395 2 2 5 4
396 2 3 4 1
397 2 3 4 2
398 
399 1
400 */

求kth

二分答案,original r-l = 1e8

离散化

1e8->5e4+5e4

次数 log(1e8)->log(5e4+5e4)

反而是80分,估计是排序操作消耗了一段时间

  1 #pragma GCC optimize(2)
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <cstring>
  6 #include <string>
  7 #include <algorithm>
  8 #include <iostream>
  9 using namespace std;
 10 #define ll long long
 11 
 12 /**
 13 log(n)=16
 14 n*log(n)*log(n)=12800000
 15 **/
 16 
 17 const double eps=1e-8;
 18 const ll mod=1e9+7;
 19 const int maxn=5e4+10;
 20 const int maxm=5e4+10;
 21 const int maxf=maxn<<2;
 22 const int maxg=maxn*18+maxf*2;
 23 ///n * log(n)[larger] (每个点在log(n)个区间中出现) + 每个区间加上两个虚拟点(最小、最大)
 24 
 25 int in_n[maxn],in_m[maxm][4],new_vir1,new_vir2;
 26 
 27 struct rec
 28 {
 29     int v,num;
 30     bool operator<(const rec &y) const
 31     {
 32         return v<y.v;
 33     }
 34 }value[maxn+maxm];
 35 int cnt_value,id_value,value_rev[maxn+maxm];
 36 
 37 struct node
 38 {
 39     int l,r,b;
 40 }f[maxf];
 41 
 42 int par[maxg],son[maxg][2],val[maxg],cnt[maxg],siz[maxg];
 43 int a[maxn],id;
 44 int minv=0,maxv=1e8,vir1=-2147483647,vir2=2147483647;
 45 int cal_num[maxn],cnt_cal_num;
 46 
 47 int chk(int x)
 48 {
 49     return son[par[x]][1]==x;
 50 }
 51 
 52 void pushup(int x)
 53 {
 54     siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
 55 }
 56 
 57 void rotate(int x)
 58 {
 59     int y=par[x];
 60     int z=par[y];
 61     int k=chk(x);
 62     int w=son[x][k^1];
 63     son[y][k]=w,par[w]=y;
 64     son[z][chk(y)]=x,par[x]=z;
 65     son[x][k^1]=y,par[y]=x;
 66     pushup(y),pushup(x);
 67 }
 68 
 69 void splay(int &root,int x,int goal=0)
 70 {
 71     int y,z;
 72     while (par[x]!=goal)
 73     {
 74         y=par[x];
 75         z=par[y];
 76         if (z!=goal)
 77         {
 78             if (chk(x)==chk(y))
 79                 rotate(y);
 80             else
 81                 rotate(x);
 82         }
 83         rotate(x);
 84     }
 85     if (!goal)
 86         root=x;
 87 }
 88 
 89 void find(int &root,int x)
 90 {
 91     if (!root)
 92         return;
 93     int cur=root;
 94     while (son[cur][x>val[cur]] && x!=val[cur])
 95         cur=son[cur][x>val[cur]];
 96     splay(root,cur);
 97 }
 98 
 99 int pre(int &root,int x)
100 {
101     find(root,x);
102     if (val[root]<x)
103         return root;
104     int cur=son[root][0];
105     while (son[cur][1])
106         cur=son[cur][1];
107     return cur;
108 }
109 
110 int succ(int &root,int x)
111 {
112     find(root,x);
113     if (val[root]>x)
114         return root;
115     int cur=son[root][1];
116     while (son[cur][0])
117         cur=son[cur][0];
118     return cur;
119 }
120 
121 void insert(int &root,int x)
122 {
123     int cur=root,p=0;
124     while (cur && val[cur]!=x)
125     {
126         p=cur;
127         cur=son[cur][x>val[cur]];
128     }
129     if (cur)
130         cnt[cur]++;
131     else
132     {
133         cur=++id;
134         if (p)
135         {
136             son[p][x>val[p]]=cur;
137             siz[p]++;
138         }
139         son[cur][0]=son[cur][1]=0;
140         val[cur]=x;
141         par[cur]=p;
142         cnt[cur]=siz[cur]=1;
143     }
144     splay(root,cur);
145 }
146 
147 void remove(int &root,int x)
148 {
149     int last=pre(root,x);
150     int next=succ(root,x);
151     splay(root,last);
152     splay(root,next,last);
153     int del=son[next][0];
154     if (cnt[del]>1)
155     {
156         cnt[del]--;
157         splay(root,del);
158     }
159     else
160         son[next][0]=0;
161     pushup(next),pushup(root);
162 }
163 
164 //int kth(int &root,int k)
165 //{
166 //    int cur=root;
167 //    while (1)
168 //    {
169 //        if (son[cur][0] && k<=siz[son[cur][0]])
170 //            cur=son[cur][0];
171 //        else if (k>siz[son[cur][0]]+cnt[cur])
172 //        {
173 //            k-=siz[son[cur][0]]+cnt[cur];
174 //            cur=son[cur][1];
175 //        }
176 //        else
177 //            return cur;
178 //    }
179 //}
180 
181 int x_rank(int &root,int x)
182 {
183     find(root,x);
184     if (val[root]>=x)
185         return siz[son[root][0]];
186     else
187         return siz[son[root][0]]+cnt[root];
188 }
189 
190 void seg_insert(int ind,int l,int r,int x,int y)
191 {
192     ///也可以build()函数,初始化
193     if (!f[ind].b)
194     {
195         insert(f[ind].b,new_vir1);  ///根节点编号为0,vir1
196         f[ind].b=id;    ///根节点编号为id
197         insert(f[ind].b,new_vir2); ///vir2
198     }
199     insert(f[ind].b,y);
200     if (l==r)
201         return;
202     int m=(l+r)>>1;
203     if (x<=m)
204         seg_insert(ind<<1,l,m,x,y);
205     else
206         seg_insert(ind<<1|1,m+1,r,x,y);
207 }
208 
209 void seg_remove(int ind,int l,int r,int x,int y)
210 {
211     remove(f[ind].b,y);
212     if (l==r)
213         return;
214     int m=(l+r)>>1;
215     if (x<=m)
216         seg_remove(ind<<1,l,m,x,y);
217     else
218         seg_remove(ind<<1|1,m+1,r,x,y);
219 }
220 
221 void cal_query_rank(int ind,int l,int r,int x,int y)
222 {
223     if (x<=l && r<=y)
224     {
225         cal_num[++cnt_cal_num]=ind;
226         return;
227     }
228     int m=(l+r)>>1;
229     if (x<=m)
230         cal_query_rank(ind<<1,l,m,x,y);
231     if (m<y)
232         cal_query_rank(ind<<1|1,m+1,r,x,y);
233 }
234 
235 int query_rank(int ind,int l,int r,int x,int y,int z)
236 {
237     if (x<=l && r<=y)
238         return x_rank(f[ind].b,z)-1;    ///减去最小虚拟点
239 
240     int m=(l+r)>>1,sum=0;
241     if (x<=m)
242         sum+=query_rank(ind<<1,l,m,x,y,z);
243     if (m<y)
244         sum+=query_rank(ind<<1|1,m+1,r,x,y,z);
245     return sum;
246 }
247 
248 int query_pre(int ind,int l,int r,int x,int y,int z)
249 {
250     if (x<=l && r<=y)
251         return val[pre(f[ind].b,z)];
252     int m=(l+r)>>1,re=new_vir1;///vir1
253     if (x<=m)
254         re=max(re,query_pre(ind<<1,l,m,x,y,z));
255     if (m<y)
256         re=max(re,query_pre(ind<<1|1,m+1,r,x,y,z));
257     return re;
258 }
259 
260 int query_succ(int ind,int l,int r,int x,int y,int z)
261 {
262     if (x<=l && r<=y)
263         return val[succ(f[ind].b,z)];
264     int m=(l+r)>>1,re=new_vir2;///vir2
265     if (x<=m)
266         re=min(re,query_succ(ind<<1,l,m,x,y,z));
267     if (m<y)
268         re=min(re,query_succ(ind<<1|1,m+1,r,x,y,z));
269     return re;
270 }
271 
272 int main()
273 {
274     int n,m,i,l,r,k,mode,x,L,R,mid;
275     scanf("%d%d",&n,&m);
276 
277     for (i=1;i<=n;i++)
278     {
279         scanf("%d",&in_n[i]);
280         value[++cnt_value]={in_n[i],i};
281     }
282     for (i=1;i<=m;i++)
283     {
284         scanf("%d",&in_m[i][0]);
285         if (in_m[i][0]==3)
286         {
287             scanf("%d%d",&in_m[i][1],&in_m[i][2]);
288             value[++cnt_value]={in_m[i][2],n+i};
289         }
290         else
291         {
292             scanf("%d%d%d",&in_m[i][1],&in_m[i][3],&in_m[i][2]);
293             if (in_m[i][0]!=2)
294                 value[++cnt_value]={in_m[i][2],n+i};
295         }
296     }
297     value[++cnt_value]={vir1,0};
298     value[++cnt_value]={vir2,0};
299 
300     sort(value+1,value+cnt_value+1);
301     value[0].v=value[1].v-1;
302     for (i=1;i<=cnt_value;i++)
303     {
304         if (value[i].v!=value[i-1].v)
305             value_rev[++id_value]=value[i].v;
306 
307         if (value[i].v==vir1 || value[i].v==vir2)
308             continue;
309 
310         if (value[i].num<=n)
311             in_n[value[i].num]=id_value;
312         else
313             in_m[value[i].num-n][2]=id_value;
314     }
315     new_vir1=1;
316     new_vir2=id_value;
317 
318     for (i=1;i<=n;i++)
319     {
320 //        scanf("%d",&x);
321         x=in_n[i];
322         seg_insert(1,1,n,i,x);
323         a[i]=x;
324     }
325 
326     for (int M=1;M<=m;M++)
327     {
328         mode=in_m[M][0];
329 //        scanf("%d",&mode);
330         if (mode==3)
331             l=in_m[M][1],k=in_m[M][2];
332 //            scanf("%d%d",&l,&k);
333         else
334             l=in_m[M][1],r=in_m[M][3],k=in_m[M][2]; ///attention!
335 
336 //            scanf("%d%d%d",&l,&r,&k);
337         if (mode==1)
338             ///log(n)*log(n)
339             printf("%d
",query_rank(1,1,n,l,r,k)+1);   ///比其小的点的数目+1
340         else if (mode==2)
341         {
342             ///log(value_range[maxv-minv])
343             ///可离散化成log(maxn+maxm),但写起来很复杂
344             ///可记录区间的最小、最大值,但写起来很麻烦,特别是涉及了数字修改
345 
346             ///每次遍历的内容都是一致的,用cal_query_rank函数记录下来
347 
348             cnt_cal_num=0;
349             cal_query_rank(1,1,n,l,r);
350 
351             L=minv,R=maxv;
352             while (L<=R)
353             {
354                 mid=(L+R)>>1;
355 
356                 x=1;
357                 for (i=1;i<=cnt_cal_num;i++)
358                     x+=x_rank(f[cal_num[i]].b,mid)-1;   ///f[index].b 会变化
359 
360                 ///log(n)*log(n)
361 //                x=query_rank(1,1,n,l,r,mid)+1;    ///
362                 if (x<=k)
363                     L=mid+1;
364                 else
365                     R=mid-1;
366             }
367             printf("%d
",value_rev[R]);    ///
368         }
369         else if (mode==3)
370         {
371             ///log(n)*log(n)
372             seg_remove(1,1,n,l,a[l]);
373             ///log(n)*log(n)
374             seg_insert(1,1,n,l,k);
375             a[l]=k;
376         }
377         else if (mode==4)
378             ///log(n)*log(n)
379             printf("%d
",value_rev[query_pre(1,1,n,l,r,k)]);
380         else
381             ///log(n)*log(n)
382             printf("%d
",value_rev[query_succ(1,1,n,l,r,k)]);
383     }
384     return 0;
385 }
386 /*
387 9 36
388 4 2 2 1 9 4 0 1 1
389 
390 1 1 5 1
391 1 1 5 2
392 1 1 5 3
393 1 1 5 4
394 1 1 5 5
395 
396 2 1 5 1
397 2 1 5 2
398 2 1 5 3
399 2 1 5 4
400 2 1 5 5
401 
402 3 3 0
403 1 1 5 3
404 3 3 1
405 1 1 5 3
406 3 3 2
407 1 1 5 3
408 3 3 3
409 1 1 5 3
410 3 3 5
411 1 1 5 3
412 3 3 10
413 1 1 5 3
414 3 3 2
415 
416 4 1 5 0
417 4 1 5 1
418 4 1 5 2
419 4 1 5 3
420 4 1 5 4
421 4 1 5 5
422 
423 5 1 5 0
424 5 1 5 1
425 5 1 5 2
426 5 1 5 3
427 5 1 5 4
428 5 1 5 9
429 5 1 5 10
430 
431 
432 9 100
433 1 1 1 1 1 1 1 1 1
434 1 1 10 1
435 1 1 10 10
436 1 1 10 5
437 2 1 10 1
438 2 1 10 9
439 2 1 10 5
440 4 1 10 1
441 4 1 10 5
442 5 1 10 1
443 5 1 10 -5
444 
445 
446 5 100
447 1 2 3 2 1
448 2 1 5 1
449 2 1 5 2
450 2 1 5 3
451 2 1 5 4
452 2 1 5 5
453 2 2 5 1
454 2 2 5 2
455 2 2 5 3
456 2 2 5 4
457 2 3 4 1
458 2 3 4 2
459 
460 1 4
461 1
462 5 1 1 -1
463 5 1 1 10
464 6 1 1 -1
465 6 1 1 10
466 
467 9 1
468 4 2 2 1 9 4 0 1 1
469 5 1 5 10
470 */

从上到下

第二个:加splay(),考虑'到刚访问的节点在之后有可能很快将再次访问'

第一个:root形参->全局变量+指针(用于修改)

第三个:

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 #define ll long long
 10 
 11 /**
 12 log(n)=16
 13 n*log(n)*log(n)=12800000
 14 **/
 15 
 16 const double eps=1e-8;
 17 const ll mod=1e9+7;
 18 const int maxn=5e4+10;
 19 const int maxf=maxn<<2;
 20 const int maxg=maxn*18+maxf*2;
 21 ///n * log(n)[larger] (每个点在log(n)个区间中出现) + 每个区间加上两个虚拟点(最小、最大)
 22 
 23 struct node
 24 {
 25     int l,r,b;
 26 }f[maxf];
 27 
 28 int par[maxg],son[maxg][2],val[maxg],cnt[maxg],siz[maxg];
 29 int a[maxn],id;
 30 int minv=0,maxv=1e8,vir1=-2147483647,vir2=2147483647;
 31 
 32 int chk(int x)
 33 {
 34     return son[par[x]][1]==x;
 35 }
 36 
 37 void pushup(int x)
 38 {
 39     siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
 40 }
 41 
 42 void rotate(int x)
 43 {
 44     int y=par[x];
 45     int z=par[y];
 46     int k=chk(x);
 47     int w=son[x][k^1];
 48     son[y][k]=w,par[w]=y;
 49     son[z][chk(y)]=x,par[x]=z;
 50     son[x][k^1]=y,par[y]=x;
 51     pushup(y),pushup(x);
 52 }
 53 
 54 void splay(int &root,int x,int goal=0)
 55 {
 56     int y,z;
 57     while (par[x]!=goal)
 58     {
 59         y=par[x];
 60         z=par[y];
 61         if (z!=goal)
 62         {
 63             if (chk(x)==chk(y))
 64                 rotate(y);
 65             else
 66                 rotate(x);
 67         }
 68         rotate(x);
 69     }
 70     if (!goal)
 71         root=x;
 72 }
 73 
 74 void find(int &root,int x)
 75 {
 76     if (!root)
 77         return;
 78     int cur=root;
 79     while (son[cur][x>val[cur]] && x!=val[cur])
 80         cur=son[cur][x>val[cur]];
 81     splay(root,cur);
 82 }
 83 
 84 int pre(int &root,int x)
 85 {
 86     find(root,x);
 87     if (val[root]<x)
 88         return root;
 89     int cur=son[root][0];
 90     while (son[cur][1])
 91         cur=son[cur][1];
 92     return cur;
 93 }
 94 
 95 int succ(int &root,int x)
 96 {
 97     find(root,x);
 98     if (val[root]>x)
 99         return root;
100     int cur=son[root][1];
101     while (son[cur][0])
102         cur=son[cur][0];
103     return cur;
104 }
105 
106 void insert(int &root,int x)
107 {
108     int cur=root,p=0;
109     while (cur && val[cur]!=x)
110     {
111         p=cur;
112         cur=son[cur][x>val[cur]];
113     }
114     if (cur)
115         cnt[cur]++;
116     else
117     {
118         cur=++id;
119         if (p)
120         {
121             son[p][x>val[p]]=cur;
122             siz[p]++;
123         }
124         son[cur][0]=son[cur][1]=0;
125         val[cur]=x;
126         par[cur]=p;
127         cnt[cur]=siz[cur]=1;
128     }
129     splay(root,cur);
130 }
131 
132 void remove(int &root,int x)
133 {
134     int last=pre(root,x);
135     int next=succ(root,x);
136     splay(root,last);
137     splay(root,next,last);
138     int del=son[next][0];
139     if (cnt[del]>1)
140     {
141         cnt[del]--;
142         splay(root,del);
143     }
144     else
145         son[next][0]=0;
146     pushup(next),pushup(root);
147 }
148 
149 //int kth(int &root,int k)
150 //{
151 //    int cur=root;
152 //    while (1)
153 //    {
154 //        if (son[cur][0] && k<=siz[son[cur][0]])
155 //            cur=son[cur][0];
156 //        else if (k>siz[son[cur][0]]+cnt[cur])
157 //        {
158 //            k-=siz[son[cur][0]]+cnt[cur];
159 //            cur=son[cur][1];
160 //        }
161 //        else
162 //            return cur;
163 //    }
164 //}
165 
166 int x_rank(int &root,int x)
167 {
168     find(root,x);
169     if (val[root]>=x)
170         return siz[son[root][0]];
171     else
172         return siz[son[root][0]]+cnt[root];
173 }
174 
175 void seg_insert(int ind,int l,int r,int x,int y)
176 {
177     ///也可以build()函数,初始化
178     if (!f[ind].b)
179     {
180         insert(f[ind].b,vir1);  ///根节点编号为0
181         f[ind].b=id;    ///根节点编号为id
182         insert(f[ind].b,vir2);
183     }
184     insert(f[ind].b,y);
185     if (l==r)
186         return;
187     int m=(l+r)>>1;
188     if (x<=m)
189         seg_insert(ind<<1,l,m,x,y);
190     else
191         seg_insert(ind<<1|1,m+1,r,x,y);
192 }
193 
194 void seg_remove(int ind,int l,int r,int x,int y)
195 {
196     remove(f[ind].b,y);
197     if (l==r)
198         return;
199     int m=(l+r)>>1;
200     if (x<=m)
201         seg_remove(ind<<1,l,m,x,y);
202     else
203         seg_remove(ind<<1|1,m+1,r,x,y);
204 }
205 
206 int query_rank(int ind,int l,int r,int x,int y,int z)
207 {
208     if (x<=l && r<=y)
209         return x_rank(f[ind].b,z)-1;    ///减去最小虚拟点
210     int m=(l+r)>>1,sum=0;
211     if (x<=m)
212         sum+=query_rank(ind<<1,l,m,x,y,z);
213     if (m<y)
214         sum+=query_rank(ind<<1|1,m+1,r,x,y,z);
215     return sum;
216 }
217 
218 int query_pre(int ind,int l,int r,int x,int y,int z)
219 {
220     if (x<=l && r<=y)
221         return val[pre(f[ind].b,z)];
222     int m=(l+r)>>1,re=vir1;
223     if (x<=m)
224         re=max(re,query_pre(ind<<1,l,m,x,y,z));
225     if (m<y)
226         re=max(re,query_pre(ind<<1|1,m+1,r,x,y,z));
227     return re;
228 }
229 
230 int query_succ(int ind,int l,int r,int x,int y,int z)
231 {
232     if (x<=l && r<=y)
233         return val[succ(f[ind].b,z)];
234     int m=(l+r)>>1,re=vir2;
235     if (x<=m)
236         re=min(re,query_succ(ind<<1,l,m,x,y,z));
237     if (m<y)
238         re=min(re,query_succ(ind<<1|1,m+1,r,x,y,z));
239     return re;
240 }
241 
242 int main()
243 {
244     int n,m,i,l,r,k,mode,x,L,R,mid;
245     scanf("%d%d",&n,&m);
246     for (i=1;i<=n;i++)
247     {
248         scanf("%d",&x);
249         seg_insert(1,1,n,i,x);
250         a[i]=x;
251     }
252     while (m--)
253     {
254         scanf("%d",&mode);
255         if (mode==3)
256             scanf("%d%d",&l,&k);
257         else
258             scanf("%d%d%d",&l,&r,&k);
259         if (mode==1)
260             ///log(n)*log(n)
261             printf("%d
",query_rank(1,1,n,l,r,k)+1);   ///比其小的点的数目+1
262         else if (mode==2)
263         {
264             ///log(value_range[maxv-minv])
265             ///可离散化成log(maxn+maxm),但写起来很复杂
266             L=minv,R=maxv;
267             while (L<=R)
268             {
269                 mid=(L+R)>>1;
270                 ///log(n)*log(n)
271                 x=query_rank(1,1,n,l,r,mid)+1;    ///
272                 if (x<=k)
273                     L=mid+1;
274                 else
275                     R=mid-1;
276             }
277             printf("%d
",R);
278         }
279         else if (mode==3)
280         {
281             ///log(n)*log(n)
282             seg_remove(1,1,n,l,a[l]);
283             ///log(n)*log(n)
284             seg_insert(1,1,n,l,k);
285             a[l]=k;
286         }
287         else if (mode==4)
288             ///log(n)*log(n)
289             printf("%d
",query_pre(1,1,n,l,r,k));
290         else
291             ///log(n)*log(n)
292             printf("%d
",query_succ(1,1,n,l,r,k));
293     }
294     return 0;
295 }
296 /*
297 9 100
298 4 2 2 1 9 4 0 1 1
299 
300 1 1 5 1
301 1 1 5 2
302 1 1 5 3
303 1 1 5 4
304 1 1 5 5
305 
306 2 1 5 1
307 2 1 5 2
308 2 1 5 3
309 2 1 5 4
310 2 1 5 5
311 
312 3 3 0
313 1 1 5 3
314 3 3 1
315 1 1 5 3
316 3 3 2
317 1 1 5 3
318 3 3 3
319 1 1 5 3
320 3 3 5
321 1 1 5 3
322 3 3 10
323 1 1 5 3
324 3 3 2
325 
326 4 1 5 0
327 4 1 5 1
328 4 1 5 2
329 4 1 5 3
330 4 1 5 4
331 4 1 5 5
332 
333 5 1 5 0
334 5 1 5 1
335 5 1 5 2
336 5 1 5 3
337 5 1 5 4
338 5 1 5 9
339 5 1 5 10
340 
341 9 100
342 1 1 1 1 1 1 1 1 1
343 1 1 10 1
344 1 1 10 10
345 1 1 10 5
346 2 1 10 1
347 2 1 10 9
348 2 1 10 5
349 4 1 10 1
350 4 1 10 5
351 5 1 10 1
352 5 1 10 -5
353 
354 */

 第二个:

  1 /**
  2 考虑到刚访问的节点在之后有可能很快将再次访问
  3 **/
  4 #include <cstdio>
  5 #include <cstdlib>
  6 #include <cmath>
  7 #include <cstring>
  8 #include <string>
  9 #include <algorithm>
 10 #include <iostream>
 11 using namespace std;
 12 #define ll long long
 13 
 14 /**
 15 log(n)=16
 16 n*log(n)*log(n)=12800000
 17 **/
 18 
 19 const double eps=1e-8;
 20 const ll mod=1e9+7;
 21 const int maxn=5e4+10;
 22 const int maxf=maxn<<2;
 23 const int maxg=maxn*18+maxf*2;
 24 ///n * log(n)[larger] (每个点在log(n)个区间中出现) + 每个区间加上两个虚拟点(最小、最大)
 25 
 26 struct node
 27 {
 28     int l,r,b;
 29 }f[maxf];
 30 
 31 int par[maxg],son[maxg][2],val[maxg],cnt[maxg],siz[maxg];
 32 int a[maxn],id;
 33 int minv=0,maxv=1e8,vir1=-2147483647,vir2=2147483647;
 34 
 35 int chk(int x)
 36 {
 37     return son[par[x]][1]==x;
 38 }
 39 
 40 void pushup(int x)
 41 {
 42     siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
 43 }
 44 
 45 void rotate(int x)
 46 {
 47     int y=par[x];
 48     int z=par[y];
 49     int k=chk(x);
 50     int w=son[x][k^1];
 51     son[y][k]=w,par[w]=y;
 52     son[z][chk(y)]=x,par[x]=z;
 53     son[x][k^1]=y,par[y]=x;
 54     pushup(y),pushup(x);
 55 }
 56 
 57 void splay(int &root,int x,int goal=0)
 58 {
 59     int y,z;
 60     while (par[x]!=goal)
 61     {
 62         y=par[x];
 63         z=par[y];
 64         if (z!=goal)
 65         {
 66             if (chk(x)==chk(y))
 67                 rotate(y);
 68             else
 69                 rotate(x);
 70         }
 71         rotate(x);
 72     }
 73     if (!goal)
 74         root=x;
 75 }
 76 
 77 void find(int &root,int x)
 78 {
 79     if (!root)
 80         return;
 81     int cur=root;
 82     while (son[cur][x>val[cur]] && x!=val[cur])
 83         cur=son[cur][x>val[cur]];
 84     splay(root,cur);
 85 }
 86 
 87 int pre(int &root,int x)
 88 {
 89     find(root,x);
 90     if (val[root]<x)
 91         return root;
 92     int cur=son[root][0];
 93     while (son[cur][1])
 94         cur=son[cur][1];
 95     splay(root,cur);
 96     return cur;
 97 }
 98 
 99 int succ(int &root,int x)
100 {
101     find(root,x);
102     if (val[root]>x)
103         return root;
104     int cur=son[root][1];
105     while (son[cur][0])
106         cur=son[cur][0];
107     splay(root,cur);
108     return cur;
109 }
110 
111 void insert(int &root,int x)
112 {
113     int cur=root,p=0;
114     while (cur && val[cur]!=x)
115     {
116         p=cur;
117         cur=son[cur][x>val[cur]];
118     }
119     if (cur)
120         cnt[cur]++;
121     else
122     {
123         cur=++id;
124         if (p)
125         {
126             son[p][x>val[p]]=cur;
127             siz[p]++;
128         }
129         son[cur][0]=son[cur][1]=0;
130         val[cur]=x;
131         par[cur]=p;
132         cnt[cur]=siz[cur]=1;
133     }
134     splay(root,cur);
135 }
136 
137 void remove(int &root,int x)
138 {
139     int last=pre(root,x);
140     int next=succ(root,x);
141     splay(root,last);
142     splay(root,next,last);
143     int del=son[next][0];
144     if (cnt[del]>1)
145     {
146         cnt[del]--;
147         splay(root,del);
148     }
149     else
150         son[next][0]=0;
151     pushup(next),pushup(root);
152 }
153 
154 //int kth(int &root,int k)
155 //{
156 //    int cur=root;
157 //    while (1)
158 //    {
159 //        if (son[cur][0] && k<=siz[son[cur][0]])
160 //            cur=son[cur][0];
161 //        else if (k>siz[son[cur][0]]+cnt[cur])
162 //        {
163 //            k-=siz[son[cur][0]]+cnt[cur];
164 //            cur=son[cur][1];
165 //        }
166 //        else
167 //        {
168 //            splay(cur);
169 //            return cur;
170 //        }
171 //    }
172 //}
173 
174 int x_rank(int &root,int x)
175 {
176     find(root,x);
177     if (val[root]>=x)
178         return siz[son[root][0]];
179     else
180         return siz[son[root][0]]+cnt[root];
181 }
182 
183 void seg_insert(int ind,int l,int r,int x,int y)
184 {
185     ///也可以build()函数,初始化
186     if (!f[ind].b)
187     {
188         insert(f[ind].b,vir1);  ///根节点编号为0
189         f[ind].b=id;    ///根节点编号为id
190         insert(f[ind].b,vir2);
191     }
192     insert(f[ind].b,y);
193     if (l==r)
194         return;
195     int m=(l+r)>>1;
196     if (x<=m)
197         seg_insert(ind<<1,l,m,x,y);
198     else
199         seg_insert(ind<<1|1,m+1,r,x,y);
200 }
201 
202 void seg_remove(int ind,int l,int r,int x,int y)
203 {
204     remove(f[ind].b,y);
205     if (l==r)
206         return;
207     int m=(l+r)>>1;
208     if (x<=m)
209         seg_remove(ind<<1,l,m,x,y);
210     else
211         seg_remove(ind<<1|1,m+1,r,x,y);
212 }
213 
214 int query_rank(int ind,int l,int r,int x,int y,int z)
215 {
216     if (x<=l && r<=y)
217         return x_rank(f[ind].b,z)-1;    ///减去最小虚拟点
218     int m=(l+r)>>1,sum=0;
219     if (x<=m)
220         sum+=query_rank(ind<<1,l,m,x,y,z);
221     if (m<y)
222         sum+=query_rank(ind<<1|1,m+1,r,x,y,z);
223     return sum;
224 }
225 
226 int query_pre(int ind,int l,int r,int x,int y,int z)
227 {
228     if (x<=l && r<=y)
229         return val[pre(f[ind].b,z)];
230     int m=(l+r)>>1,re=vir1;
231     if (x<=m)
232         re=max(re,query_pre(ind<<1,l,m,x,y,z));
233     if (m<y)
234         re=max(re,query_pre(ind<<1|1,m+1,r,x,y,z));
235     return re;
236 }
237 
238 int query_succ(int ind,int l,int r,int x,int y,int z)
239 {
240     if (x<=l && r<=y)
241         return val[succ(f[ind].b,z)];
242     int m=(l+r)>>1,re=vir2;
243     if (x<=m)
244         re=min(re,query_succ(ind<<1,l,m,x,y,z));
245     if (m<y)
246         re=min(re,query_succ(ind<<1|1,m+1,r,x,y,z));
247     return re;
248 }
249 
250 int main()
251 {
252     int n,m,i,l,r,k,mode,x,L,R,mid;
253     scanf("%d%d",&n,&m);
254     for (i=1;i<=n;i++)
255     {
256         scanf("%d",&x);
257         seg_insert(1,1,n,i,x);
258         a[i]=x;
259     }
260     while (m--)
261     {
262         scanf("%d",&mode);
263         if (mode==3)
264             scanf("%d%d",&l,&k);
265         else
266             scanf("%d%d%d",&l,&r,&k);
267         if (mode==1)
268             ///log(n)*log(n)
269             printf("%d
",query_rank(1,1,n,l,r,k)+1);   ///比其小的点的数目+1
270         else if (mode==2)
271         {
272             ///log(value_range[maxv-minv])
273             ///可离散化成log(maxn+maxm),但写起来很复杂
274             L=minv,R=maxv;
275             while (L<=R)
276             {
277                 mid=(L+R)>>1;
278                 ///log(n)*log(n)
279                 x=query_rank(1,1,n,l,r,mid)+1;    ///
280                 if (x<=k)
281                     L=mid+1;
282                 else
283                     R=mid-1;
284             }
285             printf("%d
",R);
286         }
287         else if (mode==3)
288         {
289             ///log(n)*log(n)
290             seg_remove(1,1,n,l,a[l]);
291             ///log(n)*log(n)
292             seg_insert(1,1,n,l,k);
293             a[l]=k;
294         }
295         else if (mode==4)
296             ///log(n)*log(n)
297             printf("%d
",query_pre(1,1,n,l,r,k));
298         else
299             ///log(n)*log(n)
300             printf("%d
",query_succ(1,1,n,l,r,k));
301     }
302     return 0;
303 }
304 /*
305 9 100
306 4 2 2 1 9 4 0 1 1
307 
308 1 1 5 1
309 1 1 5 2
310 1 1 5 3
311 1 1 5 4
312 1 1 5 5
313 
314 2 1 5 1
315 2 1 5 2
316 2 1 5 3
317 2 1 5 4
318 2 1 5 5
319 
320 3 3 0
321 1 1 5 3
322 3 3 1
323 1 1 5 3
324 3 3 2
325 1 1 5 3
326 3 3 3
327 1 1 5 3
328 3 3 5
329 1 1 5 3
330 3 3 10
331 1 1 5 3
332 3 3 2
333 
334 4 1 5 0
335 4 1 5 1
336 4 1 5 2
337 4 1 5 3
338 4 1 5 4
339 4 1 5 5
340 
341 5 1 5 0
342 5 1 5 1
343 5 1 5 2
344 5 1 5 3
345 5 1 5 4
346 5 1 5 9
347 5 1 5 10
348 
349 9 100
350 1 1 1 1 1 1 1 1 1
351 1 1 10 1
352 1 1 10 10
353 1 1 10 5
354 2 1 10 1
355 2 1 10 9
356 2 1 10 5
357 4 1 10 1
358 4 1 10 5
359 5 1 10 1
360 5 1 10 -5
361 
362 */

第三个:

  1 /**
  2 root
  3 指针
  4 **/
  5 #include <cstdio>
  6 #include <cstdlib>
  7 #include <cmath>
  8 #include <cstring>
  9 #include <string>
 10 #include <algorithm>
 11 #include <iostream>
 12 using namespace std;
 13 #define ll long long
 14 
 15 /**
 16 log(n)=16
 17 n*log(n)*log(n)=12800000
 18 **/
 19 
 20 const double eps=1e-8;
 21 const ll mod=1e9+7;
 22 const int maxn=5e4+10;
 23 const int maxf=maxn<<2;
 24 const int maxg=maxn*18+maxf*2;
 25 ///n * log(n)[larger] (每个点在log(n)个区间中出现) + 每个区间加上两个虚拟点(最小、最大)
 26 
 27 struct node
 28 {
 29     int l,r,b;
 30 }f[maxf];
 31 
 32 int par[maxg],son[maxg][2],val[maxg],cnt[maxg],siz[maxg];
 33 int a[maxn],id;
 34 int minv=0,maxv=1e8,vir1=-2147483647,vir2=2147483647;
 35 int *splay_value,root;
 36 
 37 int chk(int x)
 38 {
 39     return son[par[x]][1]==x;
 40 }
 41 
 42 void pushup(int x)
 43 {
 44     siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
 45 }
 46 
 47 void rotate(int x)
 48 {
 49     int y=par[x];
 50     int z=par[y];
 51     int k=chk(x);
 52     int w=son[x][k^1];
 53     son[y][k]=w,par[w]=y;
 54     son[z][chk(y)]=x,par[x]=z;
 55     son[x][k^1]=y,par[y]=x;
 56     pushup(y),pushup(x);
 57 }
 58 
 59 void splay(int x,int goal=0)
 60 {
 61     int y,z;
 62     while (par[x]!=goal)
 63     {
 64         y=par[x];
 65         z=par[y];
 66         if (z!=goal)
 67         {
 68             if (chk(x)==chk(y))
 69                 rotate(y);
 70             else
 71                 rotate(x);
 72         }
 73         rotate(x);
 74     }
 75     if (!goal)
 76     {
 77         *splay_value=x;
 78         root=x;
 79     }
 80 
 81 }
 82 
 83 void find(int x)
 84 {
 85     if (!root)
 86         return;
 87     int cur=root;
 88     while (son[cur][x>val[cur]] && x!=val[cur])
 89         cur=son[cur][x>val[cur]];
 90     splay(cur);
 91 }
 92 
 93 int pre(int x)
 94 {
 95     find(x);
 96     if (val[root]<x)
 97         return root;
 98     int cur=son[root][0];
 99     while (son[cur][1])
100         cur=son[cur][1];
101     return cur;
102 }
103 
104 int succ(int x)
105 {
106     find(x);
107     if (val[root]>x)
108         return root;
109     int cur=son[root][1];
110     while (son[cur][0])
111         cur=son[cur][0];
112     return cur;
113 }
114 
115 void insert(int x)
116 {
117     int cur=root,p=0;
118     while (cur && val[cur]!=x)
119     {
120         p=cur;
121         cur=son[cur][x>val[cur]];
122     }
123     if (cur)
124         cnt[cur]++;
125     else
126     {
127         cur=++id;
128         if (p)
129         {
130             son[p][x>val[p]]=cur;
131             siz[p]++;
132         }
133         son[cur][0]=son[cur][1]=0;
134         val[cur]=x;
135         par[cur]=p;
136         cnt[cur]=siz[cur]=1;
137     }
138     splay(cur);
139 }
140 
141 void remove(int x)
142 {
143     int last=pre(x);
144     int next=succ(x);
145     splay(last);
146     splay(next,last);
147     int del=son[next][0];
148     if (cnt[del]>1)
149     {
150         cnt[del]--;
151         splay(del);
152     }
153     else
154         son[next][0]=0;
155     pushup(next),pushup(root);
156 }
157 
158 //int kth(int &root,int k)
159 //{
160 //    int cur=root;
161 //    while (1)
162 //    {
163 //        if (son[cur][0] && k<=siz[son[cur][0]])
164 //            cur=son[cur][0];
165 //        else if (k>siz[son[cur][0]]+cnt[cur])
166 //        {
167 //            k-=siz[son[cur][0]]+cnt[cur];
168 //            cur=son[cur][1];
169 //        }
170 //        else
171 //            return cur;
172 //    }
173 //}
174 
175 int x_rank(int x)
176 {
177     find(x);
178     if (val[root]>=x)
179         return siz[son[root][0]];
180     else
181         return siz[son[root][0]]+cnt[root];
182 }
183 
184 void seg_insert(int ind,int l,int r,int x,int y)
185 {
186     ///也可以build()函数,初始化
187     if (!f[ind].b)
188     {
189         root=f[ind].b;
190         splay_value=&f[ind].b;
191         insert(vir1);  ///根节点编号为0
192 
193         f[ind].b=id;    ///根节点编号为id
194         root=f[ind].b;
195         splay_value=&f[ind].b;
196         insert(vir2);
197     }
198     root=f[ind].b;
199     splay_value=&f[ind].b;
200     insert(y);
201     if (l==r)
202         return;
203     int m=(l+r)>>1;
204     if (x<=m)
205         seg_insert(ind<<1,l,m,x,y);
206     else
207         seg_insert(ind<<1|1,m+1,r,x,y);
208 }
209 
210 void seg_remove(int ind,int l,int r,int x,int y)
211 {
212     root=f[ind].b;
213     splay_value=&f[ind].b;
214     remove(y);
215     if (l==r)
216         return;
217     int m=(l+r)>>1;
218     if (x<=m)
219         seg_remove(ind<<1,l,m,x,y);
220     else
221         seg_remove(ind<<1|1,m+1,r,x,y);
222 }
223 
224 int query_rank(int ind,int l,int r,int x,int y,int z)
225 {
226     if (x<=l && r<=y)
227     {
228         root=f[ind].b;
229         splay_value=&f[ind].b;
230         return x_rank(z)-1;    ///减去最小虚拟点
231     }
232     int m=(l+r)>>1,sum=0;
233     if (x<=m)
234         sum+=query_rank(ind<<1,l,m,x,y,z);
235     if (m<y)
236         sum+=query_rank(ind<<1|1,m+1,r,x,y,z);
237     return sum;
238 }
239 
240 int query_pre(int ind,int l,int r,int x,int y,int z)
241 {
242     if (x<=l && r<=y)
243     {
244         root=f[ind].b;
245         splay_value=&f[ind].b;
246         return val[pre(z)];
247     }
248     int m=(l+r)>>1,re=vir1;
249     if (x<=m)
250         re=max(re,query_pre(ind<<1,l,m,x,y,z));
251     if (m<y)
252         re=max(re,query_pre(ind<<1|1,m+1,r,x,y,z));
253     return re;
254 }
255 
256 int query_succ(int ind,int l,int r,int x,int y,int z)
257 {
258     if (x<=l && r<=y)
259     {
260         root=f[ind].b;
261         splay_value=&f[ind].b;
262         return val[succ(z)];
263     }
264     int m=(l+r)>>1,re=vir2;
265     if (x<=m)
266         re=min(re,query_succ(ind<<1,l,m,x,y,z));
267     if (m<y)
268         re=min(re,query_succ(ind<<1|1,m+1,r,x,y,z));
269     return re;
270 }
271 
272 int main()
273 {
274     int n,m,i,l,r,k,mode,x,L,R,mid;
275     scanf("%d%d",&n,&m);
276     for (i=1;i<=n;i++)
277     {
278         scanf("%d",&x);
279         seg_insert(1,1,n,i,x);
280         a[i]=x;
281     }
282     while (m--)
283     {
284         scanf("%d",&mode);
285         if (mode==3)
286             scanf("%d%d",&l,&k);
287         else
288             scanf("%d%d%d",&l,&r,&k);
289         if (mode==1)
290             ///log(n)*log(n)
291             printf("%d
",query_rank(1,1,n,l,r,k)+1);   ///比其小的点的数目+1
292         else if (mode==2)
293         {
294             ///log(value_range[maxv-minv])
295             ///可离散化成log(maxn+maxm),但写起来很复杂
296             L=minv,R=maxv;
297             while (L<=R)
298             {
299                 mid=(L+R)>>1;
300                 ///log(n)*log(n)
301                 x=query_rank(1,1,n,l,r,mid)+1;    ///
302                 if (x<=k)
303                     L=mid+1;
304                 else
305                     R=mid-1;
306             }
307             printf("%d
",R);
308         }
309         else if (mode==3)
310         {
311             ///log(n)*log(n)
312             seg_remove(1,1,n,l,a[l]);
313             ///log(n)*log(n)
314             seg_insert(1,1,n,l,k);
315             a[l]=k;
316         }
317         else if (mode==4)
318             ///log(n)*log(n)
319             printf("%d
",query_pre(1,1,n,l,r,k));
320         else
321             ///log(n)*log(n)
322             printf("%d
",query_succ(1,1,n,l,r,k));
323     }
324     return 0;
325 }
326 /*
327 9 100
328 4 2 2 1 9 4 0 1 1
329 
330 1 1 5 1
331 1 1 5 2
332 1 1 5 3
333 1 1 5 4
334 1 1 5 5
335 
336 2 1 5 1
337 2 1 5 2
338 2 1 5 3
339 2 1 5 4
340 2 1 5 5
341 
342 3 3 0
343 1 1 5 3
344 3 3 1
345 1 1 5 3
346 3 3 2
347 1 1 5 3
348 3 3 3
349 1 1 5 3
350 3 3 5
351 1 1 5 3
352 3 3 10
353 1 1 5 3
354 3 3 2
355 
356 4 1 5 0
357 4 1 5 1
358 4 1 5 2
359 4 1 5 3
360 4 1 5 4
361 4 1 5 5
362 
363 5 1 5 0
364 5 1 5 1
365 5 1 5 2
366 5 1 5 3
367 5 1 5 4
368 5 1 5 9
369 5 1 5 10
370 
371 
372 9 100
373 1 1 1 1 1 1 1 1 1
374 1 1 10 1
375 1 1 10 10
376 1 1 10 5
377 2 1 10 1
378 2 1 10 9
379 2 1 10 5
380 4 1 10 1
381 4 1 10 5
382 5 1 10 1
383 5 1 10 -5
384 
385 
386 1 100
387 1 2
388 1 1 2 1
389 1 1 2 2
390 */
other ways:
https://www.cnblogs.com/LadyLex/p/8006478.html

=========================================

AVL树、splay树(伸展树)和红黑树比较

https://blog.csdn.net/u010585135/article/details/41852945

实况:

AVL树时间上较慢,编程竞赛中一般不用AVL树

splay树时间上较为合适,但比红黑树稍慢,如java底层就使用红黑树编写

但由于红黑树编写极为复杂,所以编程比赛上一般不使用红黑树,而使用splay。

由于splay写起来也比较麻烦,所以有时会用其它方法替代splay,如替罪羊树,仙人掌树这些666的方法。

原文地址:https://www.cnblogs.com/cmyg/p/11301870.html