zoukankan      html  css  js  c++  java
  • 平衡树

    $Treap$ $and$ $Splay$

      我隐约记得之前说NOIP之前不再学超纲算法。但是我又开始学了。所以说我NOIP会不会凉。这真是个好问题。中考前在家无聊地报了NOI的网上同步赛,后来发现要全网公示成绩......所以赶紧学点东西骗骗分。

      记得以前初赛曾经考过一个东西叫做二叉排序树,这个东西非常好啊,平均时间复杂度是$O(logN)$的(如果插入节点的顺序随机)。但是构造数据就会被卡,树就成了一条链,退化到了O(N)。随机一下就可以不被卡啦,但是有时候要求强制在线,就用到了神奇的平衡树。

      $Treap$依靠的是随机,给每个节点随机的权值,要求根节点的权值大于两棵子树,依赖这样的随机化保证均摊复杂度比较低,树高不超过$logN$。$Treap$=$Tree$+$Heap$;

      这是我第一次用指针,其实指针还是挺有意思的,就是一定要注意不要访问空指针,否则程序就炸掉啦!

      $Splay$依靠的是信仰,复杂度似乎也是有保证的,但是比较难证。

      

      普通平衡树:https://www.lydsy.com/JudgeOnline/problem.php?id=3224

      插入x数;

      删除x数(若有多个相同的数,只删除一个);

      查询x数的排名(若有多个相同的数,输出最小的排名);

      查询排名为x的数;

      求x的前驱(前驱定义为小于x,且最大的数);

      求x的后继(后继定义为大于x,且最小的数);

      这里讲一下旋转的问题:程序中的$rotate(n,d)$是指将$n$点的$d$儿子旋转上来作为新的$n$.以$d=1$为例子:

      初始状态:

      

    1 node *k=n->ch[d];

     

    1 n->ch[d]=k->ch[d^1];

    1 k->ch[d^1]=n;

      显然这个样子转是不会破坏平衡性的~

      
      1 # include <cstdio>
      2 # include <iostream>
      3 # include <cstring>
      4 # include <string>
      5 # include <algorithm>
      6 # include <cmath>
      7 # include <cstdlib>
      8 # define R register int
      9 # define ll long long
     10 # define inf 100000008
     11 
     12 using namespace std;
     13 
     14 const int maxn=100005;
     15 int n,opt,x;
     16 struct node
     17 {
     18     int n,r,s,v;
     19     node *ch[2];
     20     void in (int x)
     21     {
     22         n=s=1;
     23         v=x;
     24         r=rand();
     25         ch[0]=ch[1]=NULL;
     26     }
     27     void update ()
     28     {
     29         s=n;
     30         if(ch[0]) s+=ch[0]->s;
     31         if(ch[1]) s+=ch[1]->s;
     32     }
     33     int cmp (int x)
     34     {
     35         if(x==v) return -1;
     36         return x>v;
     37     }
     38 }*roo,pool[maxn];
     39 
     40 node *newnode ()
     41 {
     42     static int cnt=0;
     43     return &pool[++cnt];
     44 }
     45 
     46 void rotate (node *&n,int d)
     47 {
     48     node *k=n->ch[d];
     49     n->ch[d]=k->ch[d^1];
     50     k->ch[d^1]=n;
     51     n->update();
     52     k->update();
     53     n=k;
     54 }
     55 
     56 void ins (node *&n,int x)
     57 {
     58     if(!n) n=newnode(),n->in(x);    
     59     else
     60     {
     61         int d=n->cmp(x);
     62         if(d==-1) n->n++;        
     63         else
     64         {
     65             ins(n->ch[d],x);
     66             if(n->ch[d]->r > n->r) rotate(n,d);
     67         }
     68         n->update();
     69     }
     70 }
     71 
     72 void del (node *&n,int x)
     73 {
     74     if(!n) return;
     75     int d=n->cmp(x);
     76     if(d==-1)
     77     {
     78         if(n->n > 1) --n->n;
     79         else if(!n->ch[1]) n=n->ch[0];
     80         else if(!n->ch[0]) n=n->ch[1];    
     81         else
     82         {
     83             int f=(n->ch[0]->r > n->ch[1]->r)?0:1;
     84             rotate(n,f);
     85             del(n->ch[f^1],x);
     86         }
     87         
     88     }else del(n->ch[d],x);
     89     if(n) n->update();
     90 }
     91 
     92 int ask_key (node *&n,int x)
     93 {
     94     if(!n) return 1;
     95     if(n->v==x) return (n->ch[0]?n->ch[0]->s:0)+1;
     96     if(n->v<x) return (n->ch[0]?n->ch[0]->s:0)+n->n+ask_key(n->ch[1],x);
     97     return ask_key(n->ch[0],x);
     98 }
     99 
    100 int ask_value (node *&n,int x)
    101 {
    102     if(!n||n->s<x||x<=0) return 0;
    103     int s=n->ch[0]?n->ch[0]->s:0;
    104     if(s<x&&x<=s+n->n) return n->v;
    105     if(s>=x) return ask_value(n->ch[0],x);
    106     return ask_value(n->ch[1],x-s-n->n);
    107 }
    108 
    109 int lef (node *&n,int x)
    110 {
    111     if(!n) return -inf;
    112     if(n->v >= x) return lef(n->ch[0],x);
    113     return max(n->v,lef(n->ch[1],x)); 
    114 }
    115 
    116 int rig (node *&n,int x)
    117 {
    118     if(!n) return inf;
    119     if (n->v <= x) return rig(n->ch[1], x);
    120     return min(n->v,rig(n->ch[0], x));
    121 }
    122 
    123 int main()
    124 {
    125     scanf("%d",&n);
    126     for (R i=1;i<=n;++i)
    127     {
    128         scanf("%d%d",&opt,&x);
    129         if(opt==1) ins(roo,x);
    130         else if(opt==2) del(roo,x);
    131         else if(opt==3) printf("%d
    ",ask_key(roo,x));
    132         else if(opt==4) printf("%d
    ",ask_value(roo,x));
    133         else if(opt==5) printf("%d
    ",lef(roo,x));
    134         else printf("%d
    ",rig(roo,x));
    135     }
    136     return 0;
    137 }
    Treap

     

      文艺平衡树:https://www.lydsy.com/JudgeOnline/problem.php?id=3223

      区间翻转。这种题大概只能用$Splay$来做了吧,反正我不知道$Treap$怎么做这东西.

      首先$Splay$也是一种平衡树,人气很高,常数据传比较大.它的复杂度不依赖于随机,但是也有一点玄学.它的核心操作就叫$Splay$,是一种很精巧的旋转,它的作用是将任意节点旋转到某一节点底下作为它的儿子,这样的特性就决定了她对于许多序列操作的不可替代性.关于$Splay$有几点要注意的问题:

      ·旋转不分左旋右旋($Treap$的关键在于将父亲往下转,因为有两个儿子所以要分开看;而$Splay$的核心是往父亲上面转,显然父亲只有一个);

      ·维护序列时可以打$delta$标记,但是一定要记得下放;

      说了这么多下面就来讲讲旋转:

      $Splay$的旋转很有意思,它基于一个相对简单的$rotate$操作(把自己转到父亲的位置),但是不是一味的瞎转,这样有可能虽然达成了目的却使链的长度越来越长;首先我们要找到这个节点的父亲,再找到他的爷爷,如果爷爷就是目标节点,转一下自己,退出.如果爷爷父亲自己三点共线,那么先转一下父亲,再转一下自己,否则自己转两次即可.

      如果我们要操作区间$[l,r]$,那么首先找到$l$的前驱,把它转到根的位置,再将$r$的后继转到根的右儿子,此时根的右儿子的左儿子就是我们所需要的区间了,可以用来维护一些带插入的,线段树做不了的操作.

      
      1 # include <cstdio>
      2 # include <iostream>
      3 # include <queue>
      4 # include <cstring>
      5 # include <string>
      6 # define R register int
      7 # define ll long long
      8 
      9 using namespace std;
     10 
     11 const int maxn=100005;
     12 int n,m,x,y,roo;
     13 struct node
     14 {
     15     int delta,ch[2],f,siz;
     16 }t[maxn];
     17 
     18 int read();
     19 
     20 inline void update (int id)
     21 {
     22     t[id].siz=t[ t[id].ch[0] ].siz+t[ t[id].ch[1] ].siz+1;
     23 }
     24 
     25 inline void lin (int x,int f,int d)
     26 {
     27     t[x].f=f;
     28     t[f].ch[d]=x;
     29 }
     30 
     31 int build (int l,int r)
     32 {
     33     if(l>r) return 0;
     34     int mid=(l+r)>>1;
     35     lin(build(l,mid-1),mid,0);
     36     lin(build(mid+1,r),mid,1);
     37     t[mid].delta=0;
     38     update(mid);
     39     return mid;
     40 }
     41 
     42 inline void pushdown (int n)
     43 {
     44     t[n].delta=0;
     45     t[ t[n].ch[0] ].delta^=1;
     46     t[ t[n].ch[1] ].delta^=1;
     47     swap(t[n].ch[0],t[n].ch[1]);
     48 }
     49 
     50 void write (int x)
     51 {
     52     if(!x) return;
     53     if(t[x].delta) pushdown(x);
     54     write(t[x].ch[0]);
     55     if(x!=1&&x!=n+2) printf("%d ",x-1);
     56     write(t[x].ch[1]);
     57 }
     58 
     59 inline int D (int x)
     60 {
     61     return x==t[ t[x].f ].ch[1];
     62 }
     63 
     64 void rotate (int x)
     65 {
     66     int f=t[x].f;
     67     if(f==roo) roo=x;
     68     int g=t[f].f;
     69     int mf=D(x),gf=D(f);
     70     int k=t[x].ch[mf^1];
     71     lin(k,f,mf),lin(f,x,mf^1),lin(x,g,gf);
     72     update(f),update(x);
     73 }
     74 
     75 void splay (int x,int g)
     76 {
     77     while(t[x].f!=g)
     78     {
     79         if(t[ t[x].f ].f==g) rotate(x);
     80         else if(D(x)==D(t[x].f)) rotate(t[x].f),rotate(x);
     81         else rotate(x),rotate(x);
     82     }
     83     update(x);
     84 }
     85 
     86 inline int find (int x)
     87 {
     88     int no=roo;
     89     x--;
     90     if(t[no].delta) pushdown(no);
     91     while (t[ t[no].ch[0] ].siz!=x)
     92     {
     93         if(t[ t[no].ch[0] ].siz<x)
     94             x-=t[ t[no].ch[0] ].siz+1,no=t[no].ch[1];
     95         else no=t[no].ch[0];
     96         if(t[no].delta) pushdown(no);
     97     }
     98     return no;
     99 }
    100 
    101 int main()
    102 {
    103     n=read(),m=read();
    104     roo=build(1,n+2);
    105     while(m--)
    106     {
    107         x=read(),y=read();
    108         x=find(x);
    109         splay(x,0);
    110         y=find(y+2);
    111         splay(y,roo);
    112         t[ t[y].ch[0] ].delta^=1;
    113     }
    114     write(roo);
    115     return 0;
    116 }
    117 
    118 inline int read()
    119 {
    120     int x=0;
    121     char c=getchar();
    122     while (!isdigit(c)) c=getchar();
    123     while (isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
    124     return x;
    125 }
    Splay

      营业额统计:https://www.lydsy.com/JudgeOnline/problem.php?id=1588

      题意概述:每次插入一个数,并找到以前插入过的数中和它最接近的一个作差取绝对值加起来,输出总的差;

      Treap板子题,就当练练手。最接近的一个必然是前驱或者后继...没了。

      
      1 # include <cstdio>
      2 # include <iostream>
      3 # include <cstdlib>
      4 # include <algorithm>
      5 # define inf 1000009
      6 # define R register int
      7 
      8 using namespace std;
      9 
     10 const int maxn=32770;
     11 int n,x,l,r,ans;
     12 struct node
     13 {
     14     int n,v,s,r;
     15     node *ch[2];
     16     void in (int x)
     17     {
     18         v=x;
     19         n=s=1;
     20         r=rand();
     21         ch[0]=ch[1]=NULL;
     22     }
     23     void update()
     24     {
     25         s=n;
     26         if(ch[0]) s+=ch[0]->s;
     27         if(ch[1]) s+=ch[1]->s;
     28     }
     29     int cmp (int x)
     30     {
     31         if(x==v) return -1;
     32         return x>v;
     33     }
     34 }*roo,pool[maxn];
     35 
     36 node *newnode()
     37 {
     38     static int cnt=0;
     39     return &pool[++cnt];
     40 }
     41 
     42 inline int read()
     43 {
     44     int x=0,f=1;
     45     char c=getchar();
     46     while (!isdigit(c)) { if(c=='-') f=-f; c=getchar(); }
     47     while (isdigit(c))  { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
     48     return x*f;
     49 }
     50 
     51 void rotate (node *&n,int d)
     52 {
     53     node *k=n->ch[d^1];
     54     n->ch[d^1]=k->ch[d];
     55     k->ch[d]=n;
     56     n->update();
     57     k->update();
     58     n=k;
     59 }
     60 
     61 void ins (node *&n,int x)
     62 {
     63     if(!n) n=newnode(),n->in(x);
     64     else
     65     {
     66         int d=n->cmp(x);
     67         if(d==-1) n->n++;
     68         else
     69         {
     70             ins(n->ch[d],x);
     71             if(n->r < n->ch[d]->r) rotate(n,d^1);
     72         }
     73         n->update();
     74     } 
     75 }
     76 
     77 int lef (node *&n,int x)
     78 {
     79     if(!n) return -inf;
     80     if(n->v > x) return lef(n->ch[0],x);
     81     return max(n->v,lef(n->ch[1],x));
     82 }
     83 
     84 int rig (node *&n,int x)
     85 {
     86     if(!n) return inf;
     87     if(n->v < x) return rig(n->ch[1],x);
     88     return min(n->v,rig(n->ch[0],x));
     89 }
     90 
     91 int main()
     92 {
     93     scanf("%d",&n);
     94     x=read();
     95     ans=x;
     96     ins(roo,x);
     97     for (int i=2;i<=n;++i)
     98     {
     99         x=read();
    100         l=lef(roo,x);
    101         r=rig(roo,x);
    102         if(l==-inf) ans+=r-x;
    103         else if(r==inf) ans+=x-l;
    104         else ans+=min(x-l,r-x);
    105         ins(roo,x);
    106     }
    107     printf("%d",ans);
    108     return 0;
    109 }
    营业额统计

     

      宠物收养所:https://www.lydsy.com/JudgeOnline/problem.php?id=1208

      题意概述:一个宠物收养所,当有人来且有宠物时,他就带走一个与自己的特征值最接近的宠物,如果没有宠物就在里面等,宠物同样。

      可以看出,无论什么时候,收养所里面不可能又有宠物又有人,所以可以用一棵Treap维护,顺便维护一下现在里面有几个人或是宠物就好了。其实本质上人和宠物是没有区别的,可以认为当人都在里面等的时候就是宠物领养人了(雾。不过嘛...还真是,到底是你在养宠物还是宠物在养你?每次猫猫挠我的时候,睡觉不理我的时候,我都很好奇。

      
      1 # include <cstdio>
      2 # include <iostream>
      3 # include <cstdlib>
      4 # define inf 21474836480LL
      5 
      6 using namespace std;
      7 
      8 const int maxn=80008;
      9 int n,cw,ly;
     10 long long l,r;
     11 int a;
     12 long long ans,b;
     13 
     14 struct node
     15 {
     16     int n,s,r;
     17     long long v;
     18     node *ch[2];
     19     void in (long long x)
     20     {
     21         v=x;
     22         n=s=1;
     23         r=rand();
     24         ch[0]=ch[1]=NULL;
     25     }
     26     void update()
     27     {
     28         s=n;
     29         if(ch[0]) s+=ch[0]->s;
     30         if(ch[1]) s+=ch[1]->s;
     31     }
     32     int cmp (long long x)
     33     {
     34         if(x==v) return -1;
     35         return x>v;    
     36     }
     37 }*roo,pool[maxn];
     38 
     39 node *newnode()
     40 {
     41     static int cnt=0;
     42     return &pool[++cnt];
     43 }
     44 
     45 void rotate (node *&n,int d)
     46 {
     47     node *k=n->ch[d^1];
     48     n->ch[d^1]=k->ch[d];
     49     k->ch[d]=n;
     50     n->update();
     51     k->update();
     52     n=k;
     53 }
     54 
     55 long long lef (node *&n,long long x)
     56 {
     57     if(!n) return -inf;
     58     if(n->v > x) return lef(n->ch[0],x);
     59     return max(n->v,lef(n->ch[1],x));
     60 }
     61 
     62 long long rig (node *&n,long long x)
     63 {
     64     if(!n) return inf;
     65     if(n->v < x) return rig(n->ch[1],x);
     66     return min(n->v,rig(n->ch[0],x));
     67 }
     68 
     69 void ins (node *&n,long long x)
     70 {
     71     if(!n) n=newnode(),n->in(x);
     72     else
     73     {
     74         int d=n->cmp(x);
     75         if(d==-1) n->n++;
     76         else
     77         {
     78             ins(n->ch[d],x);
     79             if(n->r < n->ch[d]->r) rotate(n,d^1);
     80         }
     81         n->update();
     82     }
     83 }
     84 
     85 void del (node *&n,long long x)
     86 {
     87     if(!n) return ;
     88     int d=n->cmp(x);
     89     if(d==-1)
     90     {
     91         if(n->n > 1) --n->n;
     92         else if(!n->ch[0]) n=n->ch[1];
     93         else if(!n->ch[1]) n=n->ch[0];
     94         else
     95         {
     96             int f=(n->ch[0]->r > n->ch[1]->r)?1:0;
     97             rotate(n,f);
     98             del(n->ch[f],x);
     99         }
    100     }else del(n->ch[d],x);
    101     if(n) n->update();
    102 }
    103 
    104 int main()
    105 {
    106     scanf("%d",&n);
    107     for (int i=1;i<=n;++i)
    108     {
    109         scanf("%d%lld",&a,&b);
    110         if(a==1&&cw==0) ins(roo,b),ly++;
    111         else if(a==1&&cw)
    112         {
    113             l=lef(roo,b);
    114             r=rig(roo,b);
    115             if(l==-inf) { ans+=r-b; del(roo,r); }
    116             else if(r==inf) { ans+=b-l; del(roo,l); }
    117             else if(b-l<=r-b) { ans+=b-l; del(roo,l); }
    118             else { ans+=r-b; del(roo,r); }
    119             cw--;
    120         }
    121         else
    122         if(a==0&&ly==0) ins(roo,b),cw++;
    123         else if(a==0&&ly)
    124         {
    125             l=lef(roo,b);
    126             r=rig(roo,b);
    127             if(l==-inf) { ans+=r-b; del(roo,r); }
    128             else if(r==inf) { ans+=b-l; del(roo,l); }
    129             else if(b-l<=r-b) { ans+=b-l; del(roo,l); }
    130             else { ans+=r-b; del(roo,r); }
    131             ly--;
    132         }
    133         ans%=1000000;
    134     }
    135     printf("%lld",ans);
    136     return 0;
    137 }
    宠物收养所

     

      永无乡:https://www.lydsy.com/JudgeOnline/problem.php?id=2733

      题意概述:有一些岛,每个岛有一个重要程度,每次询问某个岛所在的联通块内重要度第$k$小的岛的编号,或是在两岛之间修一条路.

      首先找第$k$小就可以想到平衡树啦,联通块可以拿并查集来维护,但是合并两个联通块之后怎么办呢?可以想到一个暴力的做法,每当两块合并时直接将小一点的平衡树拆掉塞进大的里面,然后再考虑优化...等等...过了!

      其实这个做法听起来暴力极了,其实还是挺科学的,这就是所谓启发式合并。因为每次都把小的往大的里边合并,所以每个点最多也只会被合并$log$次,复杂度是$O(N(logN)^2)$

      
      1 // luogu-judger-enable-o2
      2 # include <cstdio>
      3 # include <iostream>
      4 # include <cstring>
      5 # include <string>
      6 # include <algorithm>
      7 # include <cmath>
      8 # include <cstdlib>
      9 # include <queue>
     10 # include <ctime>
     11 # define R register int
     12 # define ll long long
     13 
     14 using namespace std;
     15 
     16 const int maxn=100005;
     17 int n,m,v[maxn],h,f[maxn],x,y,k,Q,pos[maxn];
     18 char s[2];
     19 struct node
     20 {
     21     int n,v,s,r;
     22     node *ch[2];
     23     void in (int x)
     24     {
     25         n=s=1;
     26         v=x;
     27         r=rand();
     28         ch[0]=ch[1]=NULL;
     29     }
     30     int cmp (int x)
     31     {
     32         if(x==v) return -1;
     33         return x>v;
     34     }
     35     void update()
     36     {
     37         s=n;
     38         if(ch[0]) s+=ch[0]->s;
     39         if(ch[1]) s+=ch[1]->s;
     40     }
     41 }*roo[maxn],pool[maxn*50];
     42 node *q[maxn];
     43 
     44 inline int read();
     45 node *newnode();
     46 void ins (node *&node,int x);
     47 inline void mer (int x,int y);
     48 void rotate (node *&n,int d);
     49 int father (int x);
     50 int ask (node *&n,int k);
     51 
     52 void write (int x)
     53 {
     54     if(x<0) putchar('-'),write(-x);
     55     else
     56     {
     57         if(x>=10) write(x/10);
     58         putchar(x%10+'0');
     59     }
     60 }
     61 
     62 int main()
     63 {
     64     srand(time(0));
     65     n=read(),m=read();
     66     for (R i=1;i<=n;++i)
     67         x=read(),f[i]=i,ins(roo[i],x),pos[x]=i;
     68     for (R i=1;i<=m;++i)
     69     {
     70         x=read(),y=read();
     71         if(x==0||y==0) continue;
     72         mer(x,y);
     73     }
     74     Q=read();
     75     int ans=0;
     76     while (Q--)
     77     {
     78         scanf("%s",s);
     79         x=read(),y=read();
     80         if(s[0]=='Q')
     81         {
     82             
     83             x=father(x);
     84             if(roo[x]->s<y) ans=-1;
     85             else ans=pos[ ask(roo[x],y) ];
     86             write(ans);
     87             putchar('
    ');
     88         }
     89         else
     90         {
     91             mer(x,y);
     92             if(x==0||y==0) continue;
     93         }
     94     }
     95     return 0;
     96 }
     97 
     98 inline int read()
     99 {
    100     int x=0;
    101     char c=getchar();
    102     while(!isdigit(c)) c=getchar();
    103     while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
    104     return x;
    105 }
    106 
    107 int father (int x) { if(x!=f[x]) return f[x]=father(f[x]); return x; }
    108 
    109 node *newnode()
    110 {
    111     static int cnt=0;
    112     return &pool[++cnt];
    113 }
    114 
    115 void ins (node *&n,int x)
    116 {
    117     if(!n) n=newnode(),n->in(x);
    118     else
    119     {
    120         int d=n->cmp(x);
    121         if(d==-1) ++n->n;
    122         else
    123         {
    124             ins(n->ch[d],x);
    125             if(n->ch[d]->r > n->r) rotate(n,d);
    126         }
    127         n->update();
    128     }
    129 }
    130 
    131 void rotate (node *&n,int d) // rotate n->ch[d] to n
    132 {
    133     node *k=n->ch[d];
    134     n->ch[d]=k->ch[d^1];
    135     k->ch[d^1]=n;
    136     n->update();
    137     k->update();
    138     n=k;
    139 }
    140 
    141 inline void mer (int x,int y)
    142 {
    143     if(roo[x]->s<roo[y]->s) swap(x,y);
    144     x=father(x);
    145     y=father(y);
    146     if(x==y) return;
    147     f[y]=x;
    148     int h=1,t=0;
    149     q[++t]=roo[y];
    150     node *k;
    151     while(h<=t)
    152     {
    153         k=q[h];
    154         ins(roo[x],k->v);
    155         if(k->ch[0]) q[++t]=k->ch[0];
    156         if(k->ch[1]) q[++t]=k->ch[1];
    157         h++;
    158     }
    159     roo[y]=roo[x];
    160 }
    161 
    162 int ask (node *&n,int k)
    163 {
    164     if(!n||k<0||n->s<k) return 0;
    165     int s=n->ch[0]?n->ch[0]->s:0;
    166     if(s<k&&k<=n->n+s) return n->v;
    167     if(s<k) return ask(n->ch[1],k-n->n-s);
    168     return ask(n->ch[0],k);
    169 }
    永无乡

    ---shzr

  • 相关阅读:
    阅读笔记06
    阅读笔记05
    学习进度03
    四则运算03
    阅读笔记04
    求最大子数组值(有环版)
    合作项目02
    新的小组信息以及项目名称与介绍
    第六周进度条
    软件工程个人作业4(课堂练习&&课堂作业)
  • 原文地址:https://www.cnblogs.com/shzr/p/9283489.html
Copyright © 2011-2022 走看看