生活随笔
收集整理的這篇文章主要介紹了
P4847 银河英雄传说V2 非旋treap
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
文章目錄
題意:
思路:
讓我們分析一下題目需要實現什么操作:
(1)(1)(1)將某個序列放到某個的后面,也就是合并兩個序列。
(2)(2)(2)將一個序列從某處斷開。
(3)(3)(3)查詢某個序列的一段和。
合并、分裂、查詢??
這不是平衡樹裸題🐎,直接上fhq?treapfhq-treapfhq?treap,太香了。
查找父親的時候每次找fatherfatherfather的時候不斷向上跳一直到根即可,最多lognlognlogn層。
注意維護序列的話,找xxx所在的位置的時候,由于其不滿足二叉搜索樹的性質,所以不能從父親向下找,但是由于根節點排名一定大于左子樹的排名,所以我們直接從當前點向上跳即可,如果這個點是父親的右兒子,那么加上左兒子大小并且+1+1+1即可。
還要注意一下,分裂的時候,分裂完之后需要將x,yx,yx,y的fatherfatherfather置為000,否則父親沒有改變會出錯的。
#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
;
int a
[N
],p
[N
],idx
;
int root
[N
],x
,y
,z
,tot
;
struct Node {int l
,r
;int rank
,val
,size
,id
,fa
;LL sum
;
}tr
[N
];int find(int x
) {return (!tr
[x
].fa
)? x
:find(tr
[x
].fa
);
}int newnode(int v
,int id
) {int u
=++tot
;tr
[u
].l
=tr
[u
].r
=0;tr
[u
].rank
=rand(); tr
[u
].val
=tr
[u
].sum
=v
;tr
[u
].size
=1; tr
[u
].id
=id
; tr
[u
].fa
=0;return u
;
}void pushup(int u
) {tr
[u
].size
=tr
[tr
[u
].l
].size
+tr
[tr
[u
].r
].size
+1;tr
[u
].sum
=tr
[u
].val
+tr
[tr
[u
].l
].sum
+tr
[tr
[u
].r
].sum
;if(tr
[u
].l
) tr
[tr
[u
].l
].fa
=u
; if(tr
[u
].r
) tr
[tr
[u
].r
].fa
=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 findrk(int v
,int root
) {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 main()
{
scanf("%d%d",&n
,&m
);for(int i
=1;i
<=n
;i
++) {int x
; scanf("%d",&x
);merge(0,newnode(x
,i
));}int all
=n
;while(m
--) {char op
[2]; int x
,y
;scanf("%s",op
);if(op
[0]=='M') {int a
,b
; scanf("%d%d",&a
,&b
);int pa
=find(a
),pb
=find(b
);if(pa
==pb
) continue;merge(pb
,pa
);} else if(op
[0]=='D') {int x
; scanf("%d",&x
);int rt
=find(x
);int rk
=findrk(x
,rt
);split(rt
,rk
-1,x
,y
);tr
[x
].fa
=tr
[y
].fa
=0;} else {int a
,b
; scanf("%d%d",&a
,&b
);int pa
=find(a
),pb
=find(b
);if(pa
!=pb
) puts("-1");else {int rk1
=findrk(a
,pa
),rk2
=findrk(b
,pb
);if(rk1
>rk2
) swap(rk1
,rk2
);split(pa
,rk2
,x
,z
); split(x
,rk1
-1,x
,y
);printf("%lld\n",tr
[y
].sum
);merge(merge(x
,y
),z
);}}}return 0;
}
總結
以上是生活随笔為你收集整理的P4847 银河英雄传说V2 非旋treap的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。