题目大意
请写一个程序,要求维护一个数列,支持以下6种操作:(请注意,格式栏中的下划线‘ _ ’表示实际输入文件中的空格)
1. 插入 INSERT_posi_tot_c1_c2_…_ctot 在当前数列的第posi个数字后插入tot个数字:c1, c2, …, ctot;若在数列首插入,则posi为0
2. 删除 DELETE_posi_tot 从当前数列的第posi个数字开始连续删除tot个数字
3. 修改 MAKE-SAME_posi_tot_c 将当前数列的第posi个数字开始的连续tot个数字统一修改为c
4. 翻转 REVERSE_posi_tot 取出从当前数列的第posi个数字开始的tot个数字,翻转后放入原来的位置
5. 求和 GET-SUM_posi_tot 计算从当前数列开始的第posi个数字开始的tot个数字的和并输出
6. 求和最大的子列 MAX-SUM 求出当前数列中和最大的一段子列,并输出最大和
解题思路
建一棵splay,维护size,sum,左起最大子区间,右起最大子区间,最大子区间,区间赋值标记,区间翻转标记。
注意使用节点回收。
code
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LF double
#define LL long long
#define Min(a,b) ((a<b)?a:b)
#define Max(a,b) ((a>b)?a:b)
#define Fo(i,j,k)
for(
int i=j;i<=k;i++)
#define Fd(i,j,k)
for(
int i=j;i>=k;i--)
using namespace std;
int const Mxn=
5*
1e5,Inf=
1e8;
int N,M,Pon,A[Mxn+
9],Val[Mxn+
9],Size[Mxn+
9],Sum[Mxn+
9],Mx[Mxn+
9],
Lmx[Mxn+
9],Rmx[Mxn+
9],Fa[Mxn+
9],Son[Mxn+
9][
2],Fill[Mxn+
9],Swap[Mxn+
9],
Bin[Mxn+
9],L,R,Tm;
void Update(
int Now){
L=Son[
Now][
0],R=Son[
Now][
1];
Size[
Now]=Size[L]+Size[R]+
1;
Sum[
Now]=Val[
Now]+Sum[L]+Sum[R];
if(R){
Tm=Max(Mx[R],Val[
Now]+Lmx[R]);
Mx[
Now]=Max(Val[
Now],Tm);
Lmx[
Now]=Max(Val[
Now],Val[
Now]+Lmx[R]);
Rmx[
Now]=Max(Val[
Now]+Sum[R],Rmx[R]);
}
else Mx[
Now]=Lmx[
Now]=Rmx[
Now]=Val[
Now];
if(L){
Tm=Max(Mx[L],Rmx[L]+Lmx[
Now]);
Mx[
Now]=Max(Mx[
Now],Tm);
Lmx[
Now]=Max(Lmx[L],Sum[L]+Lmx[
Now]);
Rmx[
Now]=Max(Rmx[L]+Val[
Now]+Sum[R],Rmx[
Now]);
}
}
int New(){
return (Bin[
0])?Bin[Bin[
0]--]:++Pon;
}
int Root,Pre,
Now;
int Make(){
Root=
New(),Pre=Root,
Now;
Val[Root]=A[
1];Fill[Root]=-Inf;Swap[Root]=
0;Son[Root][
0]=
0;
Tm=A[
0];
Fo(i,
2,Tm){
Now=
New();
Val[
Now]=A[i];Fill[
Now]=-Inf;Swap[
Now]=
0;
Son[
Now][
0]=
0;
Son[Pre][
1]=
Now;
Fa[
Now]=Pre;
Pre=
Now;
}
Son[Pre][
1]=
0;
Size[
Now=Pre]=
1;
while(
Now!=Root){
Update(
Now);
Now=Fa[
Now];
}
Update(
Now);
return Root;
}
int Side(
int Now){
Tm=Fa[
Now];
return Son[Tm][
1]==
Now;
}
int F,T;
void Rotate(
int Now){
F=Fa[
Now],T=Side(
Now);
Son[F][T]=Son[
Now][!T];
Fa[Son[
Now][!T]]=F;Tm=Side(F);
Son[Fa[F]][Tm]=
Now;
Fa[
Now]=Fa[F];
Son[
Now][!T]=F;
Fa[F]=
Now;
Update(F);
Update(
Now);
}
void Retag(
int Now,
int Tag){
if(!
Now)return;
int L=Son[
Now][
0],R=Son[
Now][
1];
if(Swap[
Now]){
swap(Son[
Now][
0],Son[
Now][
1]);
swap(Lmx[
Now],Rmx[
Now]);
Swap[L]^=
1;
Swap[R]^=
1;
Swap[
Now]=
0;
}
if(Fill[
Now]!=-Inf){
Val[
Now]=Fill[
Now];
Sum[
Now]=Fill[
Now]*Size[
Now];
Mx[
Now]=Lmx[
Now]=Rmx[
Now]=(Fill[
Now]>
0)?Sum[
Now]:Fill[
Now];
Fill[L]=Fill[R]=Fill[
Now];Fill[
Now]=-Inf;
}
if(Tag){
if(L)Retag(L,
0);
if(R)Retag(R,
0);
}
}
void Splay(
int Now,
int Pre){
while(Fa[
Now]!=Pre){
Tm=Fa[
Now];Retag(Tm,
1);
if(Fa[Tm]==Pre)Rotate(
Now);
else{
Retag(Fa[Tm],
1);
if(Side(
Now)==Side(Tm))Rotate(Fa[
Now]),Rotate(
Now);
else Rotate(
Now),Rotate(
Now);
}
}
}
int Kth(
int Now,
int Num){
while(
1){
Retag(
Now,
1);Tm=Son[
Now][
0];
if(Size[Tm]>=Num)
Now=Tm;
else if(Size[Tm]+
1==Num)return
Now;
else Num-=Size[Tm]+
1,
Now=Son[
Now][
1];
}
}
void
Get(
int Pos,
int Tot,
int &Tmp,
int &Tmp2){
Splay(Tmp=Kth(Son[
0][
1],Pos),
0);
Splay(Tmp2=Kth(Son[Tmp][
1],Tot),Tmp);
}
void Dele(
int Now){
Bin[++Bin[
0]]=
Now;
int L=Son[
Now][
0],R=Son[
Now][
1];
if(L)Dele(L);
if(R)Dele(R);
}
int Get(){
char Ch=getchar();
int V=
0,T=
1;
while(((Ch<
if(Ch==
while((Ch>=
return V*T;
}
int main(){
freopen(
"d.in",
"r",stdin);
freopen(
"d.out",
"w",stdout);
N=
Get();M=
Get();
A[
0]=N;Fo(i,
1,N)A[i]=
Get();
Son[
0][
1]=++Pon;Fa[Pon]=
0;Size[
1]=
2;
Son[
1][
1]=++Pon;Fa[Pon]=
1;Size[
2]=
1;
Fill[
1]=Fill[
2]=-Inf;Val[
1]=Val[
2]=-Inf/
10;
int Tmp=Make();
Son[
2][
0]=Tmp;Fa[Tmp]=
2;
Update(
2);
Update(
1);
char Ch;
int Pos,Tot,Tmp2,C;
Fo(cas,
1,M){
Ch=getchar();
if((Ch<
if(Ch==
scanf(
"NSERT");Pos=
Get();Tot=
Get();Pos++;
Get(Pos,
1,Tmp,Tmp2);
A[
0]=Tot;Fo(i,
1,Tot)A[i]=
Get();
Tmp=Make();
Son[Tmp2][
0]=Tmp;Fa[Tmp]=Tmp2;
Update(Tmp2);
Update(Son[
0][
1]);
}
else if(Ch==
scanf(
"ELETE");Pos=
Get();Tot=
Get();Pos++;
Get(Pos-
1,Tot+
1,Tmp,Tmp2);
Dele(Son[Tmp2][
0]);
Son[Tmp2][
0]=
0;
Update(Tmp2);
Update(Tmp);
}
else if(Ch==
Ch=getchar();
Ch=getchar();
if(Ch==
scanf(
"E-SAME");Pos=
Get();Tot=
Get();C=
Get();Pos++;
Get(Pos-
1,Tot+
1,Tmp,Tmp2);
Fill[Son[Tmp2][
0]]=C;
Retag(Son[Tmp2][
0],
1);
Update(Tmp2);
Update(Tmp);
}
else{
scanf(
"-SUM\n");
printf(
"%d\n",Mx[Son[
0][
1]]);
}
}
else if(Ch==
scanf(
"EVERSE");Pos=
Get();Tot=
Get();Pos++;
Get(Pos-
1,Tot+
1,Tmp,Tmp2);
Swap[Son[Tmp2][
0]]=
1;
Retag(Son[Tmp2][
0],
1);
Update(Tmp2);
Update(Tmp);
}
else if(Ch==
scanf(
"ET-SUM");Pos=
Get();Tot=
Get();Pos++;
Get(Pos-
1,Tot+
1,Tmp,Tmp2);
Retag(Son[Tmp2][
0],
1);
printf(
"%d\n",Sum[Son[Tmp2][
0]]);
}
}
return
0;
}
转载请注明原文地址: https://ju.6miu.com/read-24305.html