• 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的方法。

  • 相关阅读:
    [Python]爬虫v0.1
    [Python]同是新手的我,分享一些经验
    [python]闭包到底是什么鬼?
    测试Flask应用_学习笔记
    Flask模板_学习笔记
    SQL Server Alwayson概念总结
    JDBC数据库编程:ResultSet接口
    JDBC操作,执行数据库更新操作
    接口怎么实例化?
    java数据库编程:JDBC操作及数据库
  • 原文地址:https://www.cnblogs.com/cmyg/p/11301870.html
Copyright © 2020-2023  润新知