天天看點

淺談 cxx rope

一般說的淺談是永遠不會短的 

然後$qwq$本寶寶并不想講實作原理 會用就行了呗    

然後友善起見,本文規定數組$a$的第$1$位為$a[0]$

并且本文的所有$debug$為了友善看到我們$rope$長度之後的東西,會多輸出若幹位(看$debug$程式就懂了)

是以一些輸出可能跟我的不一樣(比較明顯,顯然數組越界)

進入正題

首先需要的頭檔案:

#include<ext/rope>      

需要的命名空間

using namespace __gnu_cxx;      

之後聲明一個$rope$

rope</*這裡面是填變量類型*/> ro;      

如果命名空間是$std$的話可以這麼寫:

__gnu_cxx::rope</*變量類型*/> ro;      

這裡以變量類型為$int$的$rope$來舉例

前置技能是知道怎麼通路:

擷取$ro$的第$i$位是$ro[i-1]$ 因為$rope$是從$0$開始的

淺談 cxx rope
淺談 cxx rope
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<ext/rope>
using namespace std;
__gnu_cxx::rope<int>ro;
int n,m,p;
void debug(int len)
{
    for(int i=0;i<=len;i++) printf("%d %d \n",i,ro[i]);//輸出0~len這len+1位存的是啥 
    puts("");
    return ; 
}      

前置頭檔案+函數+聲明

然後是添加删除,   

    (1). $push \_ back$和$push \_ front$

    $push \_ back(n);$

    表示在目前$rope$序列最後添加一個$n$;

    $push \_ front(n)$就是在最前面啦。

    然後測試一下:

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&m),ro.push_back(m);
    debug(n);
    return 0;
}
/*
testdata.in:
5
1 2 3 4 5
testdata.out:
0 1 
1 2 
2 3 
3 4 
4 5 
5 2576(或者别的)
*/
      

    然後又知道了如果我們通路的第$i$位要是沒指派的話會輸出随機的一個數(剛剛就是$ro[5]$我們并沒有指派)。

淺談 cxx rope
淺談 cxx rope
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&m),ro.push_front(m);
    debug(n);
    return 0;
}
/*
testdata.out
0 5 
1 4 
2 3 
3 2 
4 1 
5 0 (或者其它)
*/      

push_front

    然後自己動手試試就更能了解了。

   

    (2).一個極其好用的插入函數:$insert(pos,x)$表示在第$pos$位插入一個數$n$(就是第$pos$位變成$n$,之前的第$pos$和$pos$後面的依次向右移)

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&m),ro.push_back(m);
    debug(n);
    int ll;
    scanf("%d",&ll);
    for(int i=1;i<=ll;i++) scanf("%d%d",&m,&p),ro.insert(m,p),debug(n);
    return 0;
}
/*
testdata.in:
5
1 2 3 4 5
1
1 10
testdataout:
0 1 
1 2 
2 3 
3 4 
4 5 
5 312 (或者其他)

0 1 
1 10 
2 2 
3 3 
4 4 
5 5 
*/
      

    是以$insert(0,n)$就等同于$push \_ front(n)$

    然後這個$insert()$還有個好處是這玩意支援整個數組同時插入

    $insert(pos,a)$(a為一個數組名)表示将a數組整個插入(從$a[0]$開始一直插入,直到某一位為$0$,不插入值為$0$的這一位)

int ll;int a[5]={0,0,0,0,0};
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&m),ro.push_back(m);
    scanf("%d",&ll);
    for(int i=0;i<ll;i++) scanf("%d",&a[i]);
    int pos;scanf("%d",&pos);
    ro.insert(pos,a);
    n+=ll;
    debug(n);
    return 0;
}      
淺談 cxx rope
淺談 cxx rope
/*
testdata1.in:
5
1 2 3 4 5
3
11 12 13
1
testdata1.out:
0 1 
1 11 
2 12 
3 13 
4 2 
5 3 
6 4 
7 5 
8 0  
*/
/*
testdata2.in:
5
1 2 3 4 5
3
0 11 13
1
testdata2.out:
0 1 
1 2 
2 3 
3 4 
4 5 
5 0 
6 0 
7 0 
8 0 
*/
/*
testdata3.in:
5
1 2 3 4 5
3
11 0 13
1
testdata3.out:
0 1 
1 11 
2 2 
3 3 
4 4 
5 5 
6 0 
7 0 
8 0 
*/      

testdata

    通過第一個資料我們見識到了$insert$的整段插入,第二,三個資料說明了$insert$會插入到下一位是$0$的這一位。

    當然,萬一我們的某些題裡一定要有$0$怎麼辦?我們不想全部插入怎麼辦?

    $insert(pos,a+x,a+y)$表示将$a$數組的$a[x]$開始到$a[y-1]$位總共$y-x$位一起在$pos$插入到$rope$裡。

int ll;int a[5]={0,0,0,0,0};
int x,y;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&m),ro.push_back(m);

    scanf("%d",&ll);
    for(int i=0;i<ll;i++) scanf("%d",&a[i]);

    scanf("%d%d",&x,&y); 

    int pos;scanf("%d",&pos);

    ro.insert(pos,a+x,a+y);
    n+=ll;
    debug(n);
    return 0;
}      
淺談 cxx rope
淺談 cxx rope
/*
testdata.in:
5
1 2 3 4 5
4
11 0 13 14
1 3
1
testdata.out:
0 1 
1 0 
2 13 
3 2 
4 3 
5 4 
6 5 
7 0 
8 0 
9 0 
*/      

     

     下面開始講删除操作

      删除的函數很少啊$……$

      $erase(pos)$一個很玄學的參數,表示從$ro[pos]$開始為第$1$位 ,往後删掉共$pos+1$位

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&m),ro.push_back(m);
    debug(n);
    int pos;
    scanf("%d",&pos);
    ro.erase(pos);
    debug(n);
    return 0;
}      
淺談 cxx rope
淺談 cxx rope
/*
testdata1.in:
6
1 2 3 4 5 6
0
testdata1.out:
0 1 
1 2 
2 3 
3 4 
4 5 
5 6 
6 40 (or any)

0 2 
1 3 
2 4 
3 5 
4 6 
5 1028672837 (or any) 
6 1432107587 (or any)
*/
/*
testdata2.in:
6
1 2 3 4 5 6
1
testdata2.out:
0 1 
1 2 
2 3 
3 4 
4 5 
5 6 
6 40 (or any) 

0 1 
1 4 
2 5 
3 6 
4 0  (or any)
5 0  (or any)
6 0  (or any)

*/
/*
testdata3.in:
6
1 2 3 4 5 6
4
testdata3.out:
0 1 
1 2 
2 3 
3 4 
4 5 
5 6 
6 40 (or any)

0 1 
1 2 
2 3 
3 4 
4 1409315703 (or any)
5 1028672837 (or any)
6 1432107587 (or any)
*/      

其中$(or any)$表示是或者其他值(應該是$or \ \ else$ 的吧……本寶寶的英語好菜啊)

     $erase(pos,len)$表示從$ro[pos]$開始為第$1$位,往後删掉共$len$位。

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&m),ro.push_back(m);
    debug(n);
    int pos;int ll;
    scanf("%d%d",&pos,&ll);
    ro.erase(pos,ll);
    debug(n);
    return 0;
}
/*
testdata.in:
6
1 2 3 4 5 6
1 4
testdata.out:
0 1 
1 2 
2 3 
3 4 
4 5 
5 6 
6 40 (or else)

0 1 
1 6 
2 6816088 (or else) 
3 0 (or else)
4 0 (or else)
5 0 (or else)
6 0 (or else)
*/      

 嘤嘤嘤!插入終于寫完了,累死寶寶了$qwq$,歇一會,回來再更  $2018.7.9 \ \ 9:54$

本寶寶回來了$2018.7.9 \ \  10:38$

 然後就是修改替換轉移了

  $copy(pos,len,&x)$其中$&x$為一個指針或者數組名(不也是一個指針麼?qwq)表示将$ro[pos]$為第一位到$ro[pos+len-1]$這總共$len$位的東西指派到$a$上(數組的話從$a[0]$開始)

  $ps:\text{本小可愛這輩子都學不會指針的}$

int a[5]={0,0,0,0,0};
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&m),ro.push_back(m);
    debug(n);
    int pos;int ll;
    scanf("%d%d",&pos,&ll);
    ro.copy(pos,ll,a);
//    debug(n); 看心情,反正能不開也沒事
    for(int i=0;i<5;i++) printf(" %d ",a[i]);
    return 0;
}      
淺談 cxx rope
淺談 cxx rope
/*
testdata.in:
6
1 2 3 4 5 6
1 3
testdata.out:
0 1 
1 2 
2 3 
3 4 
4 5 
5 6 
6 40 (or else)

 2  3  4  0  0 
*/      

  

  $replace(pos,len,x)$将$ro[pos]$為第一位到$ro[pos+len-1]$這$len$位用$x$替換,順便删除這一段(具體看下面$debug$)

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&m),ro.push_back(m);
    debug(n);
    int pos;int ll;int oldval,newval;
    scanf("%d%d%d",&pos,&ll,&newval);
    ro.replace(pos,ll,newval);
    debug(n);
    return 0;
}      
淺談 cxx rope
淺談 cxx rope
/*
testdata.in:
6
1 2 3 4 5 6
1 3 11
testdata.out:
0 1 
1 2 
2 3 
3 4 
4 5 
5 6 
6 40 (or else)

0 1 
1 11 
2 5 
3 6 
4 0 (or else)
5 0 (or else)
6 0 (or else)
*/      

  我們發現,我們在$testdata$裡目的是将$1$到$3$替換成$11$然後輸出中告訴我們了,我們把原先$1$到$3$的值也順便覆寫掉了。

  其實相當于先$erase(pos,len)$然後在$insert(pos,newval)$

 

  $replace(pos,st,&x,en)$ 在$pos$插入$x$的前$en$位,其中重疊$st$位.(詳見資料)

int a[5]={0,0,0,0,0};
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&m),ro.push_back(m);
//    debug(n);
    int pos;int len;
    scanf("%d%d",&pos,&len);
    for(int i=0;i<len;i++) scanf("%d",&a[i]);
    int st,en;
    scanf("%d%d",&st,&en);
    ro.replace(pos,st,a,en);
    debug(n+4);//多輸出點看看
    return 0;
}      

UPD:從這裡起省略(or else)自己想吧 

淺談 cxx rope
淺談 cxx rope
/*
testdata1.in:
6
1 2 3 4 5 6
2 4
11 12 13 14
0 1
testdata1.out:
0 1 
1 2 
2 11 
3 3 
4 4 
5 5 
6 6 
7 0 
8 0 
9 0 
10 1658256847 
*/
/*
testdata2.in:
6
1 2 3 4 5 6
2 4
11 12 13 14
0 2
testdata2.out:
0 1 
1 2 
2 11 
3 12 
4 3 
5 4 
6 5 
7 6 
8 0 
9 0 
10 794409564 
*/
/*
testdata3.in:
6
1 2 3 4 5 6
2 4
11 12 13 14
1 4
testdata3.out:
0 1 
1 2 
2 11 
3 12 
4 13 
5 14 
6 4 
7 5 
8 6 
9 0 
10 0 
*/
/*
testdata4.in:
6
1 2 3 4 5 6
2 4
11 12 13 14
5 4
testdata4.out:
0 1 
1 2 
2 11 
3 12 
4 13 
5 14 
6 0 
7 0 
8 0 
9 0 
10 926115120 
*/      

  我們發現,當$st=0$時,相當于直接從$a$裡插入長度為$en$,$st!=0$時是覆寫$st$位插入,如$testdata3$我們本應該是在$ro[6]$的$3$被覆寫掉了。

  而又如$testdata4$當覆寫的長度大于我們要加的長度的時候,原先的就會全被清除。  

  $substr(pos,x)$提取從$pos$開始$x$個。

另外就是$rope$支援$size()$調取大小,支援$swap()$

以上這些如果是$char$類型的話還會有彩蛋呢$……$但是一般這幾個操作就夠了(其實是本寶寶就知道這些了)

然後就……

本文完結撒花了 吧……

希望能對大家有所幫助。

繼續閱讀