这是Antimonysbguy的题单的题解
当然后面那几道~~ 毒瘤题~~本蒟蒻也写不来
文章目录
T1 Sum
见 学习笔记
#include<bits/stdc++.h>
using namespace std;
#define in Read()
int in{
int i=0,f=1;char ch=0;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch)) i=(i<<1)+(i<<3)+ch-48,ch=getchar();
return i*f;
}
const int N=33000;
int n,root,ans;
struct Tree{
int lch,rch,fa,val;
#define lch(p) tre[(p)].lch
#define rch(p) tre[(p)].rch
#define fa(p) tre[(p)].fa
#define val(p) tre[(p)].val
}tre[N];
//void print_tree(int p){
// printf("%d: %d %d\n",p,lch(p),rch(p));
// if(lch(p)) print_tree(lch(p));
// if(rch(p)) print_tree(rch(p));
//}
void insert(int p,int rt){
if(val(p)<val(rt)){
if(!lch(rt)){
lch(rt)=p;
fa(p)=rt;
}else insert(p,lch(rt));
}
else{
if(!rch(rt)){
rch(rt)=p;
fa(p)=rt;
}else insert(p,rch(rt));
}
return;
}
bool as_right(int p){
return p==rch(fa(p));
}
void rotate(int x){
if(as_right(x)){
int f=fa(x),s=lch(x);
fa(x)=fa(f);
as_right(f)?rch(fa(f))=x:lch(fa(f))=x;
fa(f)=x;
lch(x)=f;
fa(s)=f;
rch(f)=s;
}else{
int f=fa(x),s=rch(x);
fa(x)=fa(f);
as_right(f)?rch(fa(f))=x:lch(fa(f))=x;
fa(f)=x;
rch(x)=f;
fa(s)=f;
lch(f)=s;
}
return;
}
void splay(int x){
while(fa(x)){
int y=fa(x),z=fa(y);
if(!z) rotate(x);
else{
if(as_right(x)==as_right(y))
rotate(y),rotate(x);
else
rotate(x),rotate(x);
}
}
root=x;
return;
}
int qmin(int p){
int res=lch(p);
if(!res) return res;
while(rch(res)) res=rch(res);
return res;
}
int qmax(int p){
int res=rch(p);
if(!res) return res;
while(lch(res)) res=lch(res);
return res;
}
int query(int p){
int pre=qmin(p),suf=qmax(p),res=2147483647;
if(pre) res=min(res,val(p)-val(pre));
if(suf) res=min(res,val(suf)-val(p));
return res;
}
void solve(int p){
insert(p,root);
splay(p);
ans+=query(p);//printf("ans+=%d\n",query(p));
return;
}
int main(){
n=in;
val(1)=in;root=1;
ans+=val(1);
for(int i=2;i<=n;++i){
val(i)=in;
solve(i);
//print_tree(root);
}
printf("%d\n",ans);
return 0;
}
T2 文艺Treap
见学习笔记
#include<bits/stdc++.h>
using namespace std;
#define in Read()
int in{
int i=0,f=1;char ch=0;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch)) i=(i<<1)+(i<<3)+ch-48,ch=getchar();
return i*f;
}
const int N=1e5+5;
int n,m,root,tot;
struct Tree{
int lch,rch,siz,tag,pri,val;
#define lch(p) tre[(p)].lch
#define rch(p) tre[(p)].rch
#define siz(p) tre[(p)].siz
#define tag(p) tre[(p)].tag
#define pri(p) tre[(p)].pri
#define val(p) tre[(p)].val
}tre[N];
void push_up(int p){
siz(p)=siz(lch(p))+siz(rch(p))+1;
return;
}
void push_down(int p){
if(!tag(p)) return;
swap(lch(p),rch(p));
tag(lch(p))^=1;
tag(rch(p))^=1;
tag(p)=0;
return;
}
void print_tree(int p){
push_down(p);
if(lch(p)) print_tree(lch(p));
printf("%d ",val(p));
if(rch(p)) print_tree(rch(p));
return;
}
int merge(int x,int y){
if(!x||!y) return x+y;
if(pri(x)<pri(y)){
push_down(x);
rch(x)=merge(rch(x),y);
push_up(x);
return x;
}else{
push_down(y);
lch(y)=merge(x,lch(y));
push_up(y);
return y;
}
}
void split(int rt,int k,int &x,int &y){
if(!rt){
x=y=0;
return;
}
push_down(rt);
if(k>=siz(lch(rt))+1){
x=rt;
split(rch(rt),k-siz(lch(rt))-1,rch(x),y);
}else{
y=rt;
split(lch(rt),k,x,lch(y));
}
push_up(rt);
return;
}
void insert(int id){
++tot;
val(tot)=id;
pri(tot)=rand();
siz(tot)=1;
root=merge(root,tot);
return;
}
void rollover(int l,int r){
int x,y,z;
split(root,r,x,y);
split(x,l-1,x,z);
tag(z)^=1;
root=merge(merge(x,z),y);
return;
}
int main(){
srand(time(0));
n=in,m=in;
for(int i=1;i<=n;++i) insert(i);
for(int i=1;i<=m;++i){
int l=in,r=in;
rollover(l,r);
}
print_tree(root);
return 0;
}
Splay
- 要建两个守卫(正无穷和负无穷)防止翻转的时候出现一些意想不到的问题其实就是翻转的时候需要 l − 1 , r + 1 l-1,r + 1 l−1,r+1,两个哨兵防止树裂开
- 非常有意义的使用递归建树,省时间
#include<bits/stdc++.h>
using namespace std;
#define in Read()
int in{
int i=0,f=1;char ch=0;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch)) i=(i<<1)+(i<<3)+ch-48,ch=getchar();
return i*f;
}
const int N=1e5+5;
const int INF=2147483647;
int n,m,root,tot,a[N];
struct Tree{
int lch,rch,tag,val,siz,fa;
#define lch(p) tre[(p)].lch
#define rch(p) tre[(p)].rch
#define siz(p) tre[(p)].siz
#define tag(p) tre[(p)].tag
#define val(p) tre[(p)].val
#define fa(p) tre[(p)].fa
}tre[N];
bool as(int p){
return p==rch(fa(p));
}
void push_up(int p){
siz(p)=siz(lch(p))+siz(rch(p))+1;
return;
}
void push_down(int p){
if(!tag(p)) return;
tag(p)=0;
swap(lch(p),rch(p));
if(lch(p)) tag(lch(p))^=1;
if(rch(p)) tag(rch(p))^=1;
return;
}
void print_tree(int p){
push_down(p);
if(lch(p)) print_tree(lch(p));
if(val(p)!=-INF&&val(p)!=INF) printf("%d ",val(p));
if(rch(p)) print_tree(rch(p));
return;
}
int build(int fa,int l,int r){
if(l>r) return 0;
int mid=l+r>>1;
int p=++tot;
val(p)=a[mid];
fa(p)=fa;
tag(p)=0;
lch(p)=build(p,l,mid-1);
rch(p)=build(p,mid+1,r);
push_up(p);
return p;
}
int find(int x){
int rt=root;
while(true){
push_down(rt);
if(x<=siz(lch(rt))) rt=lch(rt);
else{
x-=siz(lch(rt))+1;
if(!x) return rt;
rt=rch(rt);
}
}
}
void rotate(int x){
int y=fa(x),f=fa(y);
if(as(x)){
int s=lch(x);
fa(x)=f;
(as(y)?rch(f):lch(f))=x;
fa(y)=x;
lch(x)=y;
fa(s)=y;
rch(y)=s;
}else{
int s=rch(x);
fa(x)=f;
(as(y)?rch(f):lch(f))=x;
fa(y)=x;
rch(x)=y;
fa(s)=y;
lch(y)=s;
}
return;
}
void splay(int x){
while(fa(x)){
int y=fa(x),z=fa(y);
if(!z) rotate(x);
else{
if(as(x)==as(y)) rotate(y),rotate(x);
else rotate(x),rotate(x);
}
}
root=x;
return;
}
void reverse(int l,int r){
l=find(l-1),r=find(r+1);
splay(l);
splay(r);
tag(rch(lch(root)))^=1;
return;
}
int main(){
n=in,m=in;
a[1]=-INF,a[n+2]=INF;
for(int i=1;i<=n;++i) a[i+1]=i;
root=build(0,1,n+2);print_tree(root);puts("");
for(int i=1;i<=m;++i){
int l=in+1,r=in+1;
reverse(l,r);print_tree(root);puts("");
}
print_tree(root);puts("");
return 0;
}
T3 普通Treap
- 插入:搜到一个空节点,塞进去
- 删除:搜点,
splay
,删点,合并左右子树 - 查排名:左子树大小+1
- 问排名:往左右子树走
- 前驱:
splay
,左儿子中查最大查询数不一定在序列内,在树上走的时候记录一下即可 - 后继:
splay
,右儿子中查最小查询数不一定在序列内,在树上走的时候记录一下即可
个人觉得splay
好写
打代码的时候这些细节都让我心惊胆战的qwq😭
如果又M又T说明多半是死循环
splay
码炸了,写treap
去
为什么大家都写的带旋treap
,非旋treap
它不香吗
实在码不了了,大家见谅
真♂又好写又好调