生活随笔
收集整理的這篇文章主要介紹了
P2596 [ZJOI2006]书架 无旋treap 按照排名分裂
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
文章目錄
題意:
實現如下操作:
思路:
fhq-treap板子辣,不要被他的編號誤導了,我們還是需要按照排名來分裂,從上到下標號1?n1-n1?n即可,注意在按照排名分裂的時候findrankfindrankfindrank函數與按照權值分裂是不同的,因為他不滿足二叉樹的性質,那么怎么得到排名呢?可以發現其中序遍歷在他前面遍歷的個數+1+1+1就是他的排名,所以我們往上暴跳記錄一下有多少在他前面就好了,復雜度O(logn)O(logn)O(logn)。
其他的都是一些基本操作了,代碼很好寫,基本沒bug。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=1000010,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
,m
,x
,y
,z
,h
,k
,root
,tot
;
int p
[N
],has
[N
];
struct Node
{int l
,r
;int rank
,val
,id
,size
;int fa
;
}tr
[N
<<2];void pushup(int u
) {tr
[u
].size
=tr
[tr
[u
].l
].size
+tr
[tr
[u
].r
].size
+1;tr
[tr
[u
].l
].fa
=u
; tr
[tr
[u
].r
].fa
=u
;
}int newnode(int id
,int val
) {int u
=++tot
;tr
[u
]={0,0,rand(),val
,id
,1};return u
;
}void split(int u
,int k
,int &x
,int &y
) {if(!u
) { x
=y
=0; return; }if(k
<=tr
[tr
[u
].l
].size
) y
=u
,split(tr
[u
].l
,k
,x
,tr
[u
].l
);else x
=u
,split(tr
[u
].r
,k
-tr
[tr
[u
].l
].size
-1,tr
[u
].r
,y
);pushup(u
);
}int merge(int u
,int v
) {if(!u
||!v
) return u
+v
;if(tr
[u
].rank
<tr
[v
].rank
) {tr
[u
].r
=merge(tr
[u
].r
,v
);pushup(u
);return u
;}else {tr
[v
].l
=merge(u
,tr
[v
].l
);pushup(v
);return v
;}
}int findrank(int v
) {int ans
=tr
[v
].size
-tr
[tr
[v
].r
].size
;while(v
!=root
) {if(v
==tr
[tr
[v
].fa
].r
) ans
+=tr
[tr
[v
].fa
].size
-tr
[v
].size
;v
=tr
[v
].fa
;}return ans
;
}int findsize(int k
) {int u
=root
;while(1) {if(tr
[tr
[u
].l
].size
>=k
) u
=tr
[u
].l
;else if(tr
[tr
[u
].l
].size
+1==k
) return tr
[u
].val
;else k
-=tr
[tr
[u
].l
].size
+1,u
=tr
[u
].r
;}
}int main()
{
scanf("%d%d",&n
,&m
);for(int i
=1;i
<=n
;i
++) scanf("%d",&p
[i
]),root
=merge(root
,newnode(i
,p
[i
])),has
[p
[i
]]=i
;while(m
--) {char op
[10]; int xx
;scanf("%s%d",op
,&xx
);if(op
[0]=='T') {int id
=has
[xx
];int rank
=findrank(id
);split(root
,rank
,x
,y
);split(x
,rank
-1,x
,z
);root
=merge(merge(z
,x
),y
);}else if(op
[0]=='B') {int id
=has
[xx
];int rank
=findrank(id
);split(root
,rank
,x
,y
);split(x
,rank
-1,x
,z
);root
=merge(merge(x
,y
),z
);}else if(op
[0]=='I') {int yy
; scanf("%d",&yy
);if(!yy
) continue;int id
=has
[xx
];int rank
=findrank(id
);if(yy
>0) {split(root
,rank
,x
,y
); split(x
,rank
-1,x
,z
);split(y
,1,y
,h
); root
=merge(merge(merge(x
,y
),z
),h
);}else {split(root
,rank
,x
,y
); split(x
,rank
-1,x
,z
);split(x
,rank
-2,x
,h
); root
=merge(merge(merge(x
,z
),h
),y
);}}else if(op
[0]=='A') {int id
=has
[xx
];int rank
=findrank(id
);printf("%d\n",rank
-1);} else {printf("%d\n",findsize(xx
));}}return 0;
}
總結
以上是生活随笔為你收集整理的P2596 [ZJOI2006]书架 无旋treap 按照排名分裂的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。