洛谷 2042 BZOJ 1500 NOI 2005 维护数列

时间:2023-03-09 16:08:14
洛谷 2042 BZOJ 1500 NOI 2005 维护数列

【题意概述】

  维护一个数列,要求支持以下6种操作:

 洛谷 2042 BZOJ 1500 NOI 2005 维护数列

【题解】

  大Boss。。。可以用Treap解决

  需要用到垃圾回收、线性建树。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define ls (a[u].l)
#define rs (a[u].r)
using namespace std;
const int maxn=;
int n,m,k,x,y,z,top,root,recs[maxn],bs[maxn];//recs-->recycle_stack, bs-->build_stack
char c,c2;
struct treap{int l,r,size,rnd,v,sum,max,lsum,rsum,num; bool same,rev;}a[maxn];
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
inline int max(int x,int y){return x>y?x:y;}
inline int newnode(int v){a[recs[top--]]=(treap){,,,rand(),v,v,v,v,v,,,}; return recs[top+];}//新建节点
void recycle(int u){if(u) recs[++top]=u,recycle(ls),recycle(rs);}//垃圾回收
inline void reverse(int u){//区间翻转
swap(ls,rs); swap(a[u].lsum,a[u].rsum);
a[ls].rev^=; a[rs].rev^=;
}
inline void set_same(int u,int v){//区间设为同个数
a[u].same=; a[u].v=a[u].num=v; a[u].sum=v*a[u].size;
a[u].max=a[u].lsum=a[u].rsum=(v>=?a[u].sum:v);
}
void down(int u){//下传标记
if(a[u].rev){
if(ls) reverse(ls);
if(rs) reverse(rs);
a[u].rev^=;
}
if(a[u].same){
if(ls) set_same(ls,a[u].num);
if(rs) set_same(rs,a[u].num);
a[u].same=a[u].num=;
}
}
void up(int u){//上传标记
a[u].size=a[ls].size+a[rs].size+;
a[u].sum=a[ls].sum+a[rs].sum+a[u].v;
a[u].max=max(max(a[ls].max,a[rs].max),max(a[ls].rsum,)+a[u].v+max(a[rs].lsum,));
a[u].lsum=max(a[ls].lsum,a[ls].sum+a[u].v+max(a[rs].lsum,));
a[u].rsum=max(a[rs].rsum,a[rs].sum+a[u].v+max(a[ls].rsum,));
}
void split(int u,int k,int &x,int &y){//分裂
down(u);
if(!k){x=; y=u; return;}
if(a[u].size==k){x=u; y=; return;}
if(a[ls].size>=k) split(ls,k,x,ls),y=u;
else split(rs,k-a[ls].size-,rs,y),x=u;
up(u);
}
int merge(int x,int y){//合并
if(!x||!y) return x+y;
if(a[x].rnd<a[y].rnd){down(x); a[x].r=merge(a[x].r,y); up(x); return x;}
else{down(y); a[y].l=merge(x,a[y].l); up(y); return y;}
}
void build(int &root,int n){//线性建树
int bstop=; bs[++bstop]=newnode(read());
for(int i=;i<n;i++){
int now=newnode(read());
while(top&&a[now].rnd<a[bs[bstop]].rnd) up(bs[bstop]),a[now].l=bs[bstop--];
if(bstop) a[bs[bstop]].r=now;
bs[++bstop]=now;
}
while(bstop) up(bs[bstop--]);
root=bs[];
}
void out(int u){
if(ls) out(ls);
printf("%d ",a[u].v);
if(rs) out(rs);
}
void Insert(){//插入
int x,y,insroot=;
split(root,read(),x,y);
build(insroot,read());
root=merge(x,merge(insroot,y));
//out(root);
}
void Delete(){recycle(y); y=;}//删除
void Prepare(){
srand();
for(int i=maxn;i;i--) recs[++top]=i;
a[].max=a[].lsum=a[].rsum=-2e9;
}
int main(){
Prepare();
n=read(); m=read(); build(root,n); //out(root);
//for(int i=1;i<=n;i++) root=merge(root,newnode(read()));
while(m--){
c=getchar(); while(c!='I'&&c!='D'&&c!='K'&&c!='R'&&c!='G'&&c!='X') c=getchar();
c2=getchar(); while(c2!='-'&&c2!=' ') c2=getchar();
if(c=='X'){//max_sum
printf("%d\n",a[root].same?(a[root].num?a[root].num*a[root].size:a[root].num):a[root].max);
continue;
}
if(c=='I'){Insert(); continue;}//insert
split(root,read()-,x,y);
split(y,read(),y,z);
if(c=='D') Delete();//delete
if(c=='K') set_same(y,read());//set_same
if(c=='R') a[y].rev^=,reverse(y);//reverse
if(c=='G') printf("%d\n",a[y].same?a[y].num*a[y].size:a[y].sum);//get_sum
root=merge(merge(x,y),z);
}
return ;
}