平衡树裸题##
为了熟悉一下平衡树,来做了一下这道码农题,
虽然辛苦,但确实对 (FhqTreap) 的理解加深了不少。
下面贴上没有优化,开了 (O2) 和各种卡常勉强过去的代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
using namespace std;
typedef long long LL;
const int MAXN=5000010;
const int inf=0x3f3f3f3f;
const LL INF=0x3f3f3f3f3f3f3f3f;
int n,m;
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
}
struct FhqTreap{
int L[MAXN],R[MAXN],tag[MAXN],rev[MAXN],siz[MAXN],key[MAXN],tot,root;
int val[MAXN],sum[MAXN],lx[MAXN],rx[MAXN],mx[MAXN];
inline int newnode(int value){
//cout<<value<<endl;
tag[++tot]=inf,val[tot]=value,sum[tot]=value,siz[tot]=1,key[tot]=rand();
if(value>0) lx[tot]=rx[tot]=mx[tot]=value;
else lx[tot]=rx[tot]=0,mx[tot]=value;
return tot;
}
inline void pushdown(int id){
if(tag[id]!=inf){
sum[L[id]]=tag[id]*siz[L[id]],val[L[id]]=tag[L[id]]=tag[id];
sum[R[id]]=tag[id]*siz[R[id]],val[R[id]]=tag[R[id]]=tag[id];
if(tag[id]>0)
lx[L[id]]=rx[L[id]]=mx[L[id]]=sum[L[id]],
lx[R[id]]=rx[R[id]]=mx[R[id]]=sum[R[id]];
else
lx[L[id]]=rx[L[id]]=lx[R[id]]=rx[R[id]]=0,
mx[L[id]]=mx[R[id]]=tag[id];
tag[id]=inf;
rev[id]=0;
}
if(rev[id]){
swap(L[L[id]],R[L[id]]),swap(lx[L[id]],rx[L[id]]);
swap(L[R[id]],R[R[id]]),swap(lx[R[id]],rx[R[id]]);
rev[L[id]]^=1,rev[R[id]]^=1;
rev[id]=0;
}
}
inline void pushup(int id){
siz[id]=siz[L[id]]+siz[R[id]]+1;
sum[id]=sum[L[id]]+sum[R[id]]+val[id];
lx[id]=max(lx[L[id]],sum[L[id]]+val[id]+lx[R[id]]);
rx[id]=max(rx[R[id]],sum[R[id]]+val[id]+rx[L[id]]);
mx[id]=max(max(mx[L[id]],mx[R[id]]),rx[L[id]]+lx[R[id]]+val[id]);
}
inline void split(int id,int size,int &x,int &y){
if(!id) x=y=0;
else{
pushdown(id);
if(size>siz[L[id]])
x=id,split(R[id],size-siz[L[id]]-1,R[id],y);
else
y=id,split(L[id],size,x,L[id]);
pushup(id);
}
}
inline int merge(int x,int y){
if(!x||!y) return x+y;
if(key[x]>key[y]){
pushdown(x);
R[x]=merge(R[x],y);
pushup(x);
return x;
}
else{
pushdown(y);
L[y]=merge(x,L[y]);
pushup(y);
return y;
}
}
inline void insert(){
int ins=0,pos=read(),num=read();
for(register int i=1;i<=num;i++) ins=merge(ins,newnode(read()));
int x,y;
split(root,pos,x,y);
root=merge(merge(x,ins),y);
}
inline void del(){
int pos=read(),num=read();
int x,y,z;
split(root,pos-1,x,y);
split(y,num,y,z);
root=merge(x,z);
}
inline void update(){
int pos=read(),num=read(),value=read();
int x,y,z;
split(root,pos-1,x,y);
split(y,num,y,z);
sum[y]=1ll*value*siz[y];
val[y]=tag[y]=value;
if(value>0) lx[y]=rx[y]=mx[y]=sum[y];
else lx[y]=rx[y]=0,mx[y]=value;
root=merge(merge(x,y),z);
}
inline void reverse(){
int pos=read(),num=read();
int x,y,z;
split(root,pos-1,x,y);
split(y,num,y,z);
rev[y]^=1;
swap(L[y],R[y]),swap(lx[y],rx[y]);
root=merge(merge(x,y),z);
}
inline void getsum(){
int pos=read(),num=read(),x,y,z;
split(root,pos-1,x,y);
split(y,num,y,z);
printf("%d
",sum[y]);
root=merge(merge(x,y),z);
}
inline void maxsum(){
printf("%d
",mx[root]);
}
}fhq;
int main(){
srand(time(0));
n=read(),m=read();
for(register int i=1;i<=n;i++)
fhq.root=fhq.merge(fhq.root,fhq.newnode(read()));
char opt[20];
while(m--){
scanf("%s",opt);
if(opt[0]=='I') fhq.insert();
else if(opt[0]=='D') fhq.del();
else if(opt[0]=='R') fhq.reverse();
else if(opt[0]=='G') fhq.getsum();
else if(opt[0]=='M'&&opt[2]=='K') fhq.update();
else if(opt[0]=='M'&&opt[2]=='X') fhq.maxsum();
}
return 0;
}
其实数组容量不需要开那么大, 有点太极限了, 贴着内存限制过去的
题面上说了, 同时在数列中的数不超过 (5cdot 10^5) 那么可以搞一个 (queue),
把删除之后的节点编号放进去, 就像一个内存回收器一样.