题目链接
请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线 _
表示实际输入文件中的空格)

输入格式
第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M 表示要进行的操作数目。
第 2 行包含 N 个数字,描述初始时的数列。
以下 M 行,每行一条命令,格式参见问题描述中的表格。
输出格式
对于输入数据中的 GET-SUM
和 MAX-SUM
操作,向输出文件依次打印结果,每个答案(数字)占一行。
数据范围与约定
你可以认为在任何时刻,数列中至少有 1 个数。
输入数据一定是正确的,即指定位置的数在数列中一定存在。
50% 的数据中,任何时刻数列中最多含有 30000 个数;100% 的数据中,任何时刻数列中最多含有 500000 个数。
100% 的数据中,任何时刻数列中任何一个数字均在 [−1000,1000] 内。
100% 的数据中,M≤20000,插入的数字总数不超过 4000000 个,输入文件大小不超过 20 MBytes。
输入样例:
输出样例:
解题思路
splay,动态开点,内存回收机制
开两个懒标记:same,rev,表示修改和翻转标记,这两个标记其一的改变不会造成另一个的变化,可用常见数据结构维护,而操作涉及 插入 和 删除 操作,线段树不好维护,而 splay 很好操作,即将对应区间操作转化为某一棵子树的操作,而由于插入的数据很大,为了避免超内存,可引入内存回收机制,即进行删除操作时可以将删除的节点编号回收。其他操作同线段树
- 时间复杂度:O((n+m)×logn)
代码
#include <bits/stdc++.h>
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=5e5+5,inf=1e9;
int n,m,a[N],save[N],cnt,root;
struct Tr
{
int s[2],p,v,sz,lmx,rmx,mx,sum,same,rev;
void init(int _p,int _v)
{
p=_p;
v=mx=sum=_v;
s[0]=s[1]=same=rev=0;
lmx=rmx=max(0,v);
sz=1;
}
}tr[N];
void pushup(int u)
{
auto &p=tr[u],&l=tr[p.s[0]],&r=tr[p.s[1]];
p.sz=l.sz+r.sz+1;
p.sum=l.sum+r.sum+p.v;
p.lmx=max(l.lmx,l.sum+p.v+r.lmx);
p.rmx=max(r.rmx,r.sum+p.v+l.rmx);
p.mx=max({l.mx,r.mx,l.rmx+p.v+r.lmx});
}
void pushdown(int u)
{
auto &p=tr[u],&l=tr[tr[u].s[0]],&r=tr[tr[u].s[1]];
if(p.rev)
{
swap(l.s[0],l.s[1]),swap(l.lmx,l.rmx);
swap(r.s[0],r.s[1]),swap(r.lmx,r.rmx);
p.rev=0,l.rev^=1,r.rev^=1;
}
if(p.same)
{
l.same=1,l.v=p.v,l.sum=l.sz*p.v;
r.same=1,r.v=p.v,r.sum=r.sz*p.v;
if(p.v>0)
{
l.lmx=l.rmx=l.mx=l.sum;
r.lmx=r.rmx=r.mx=r.sum;
}
else
{
l.mx=p.v,l.lmx=l.rmx=0;
r.mx=p.v,r.lmx=r.rmx=0;
}
tr[u].same=0;
}
}
int build(int l,int r,int p)
{
int u=save[cnt--];
int mid=l+r>>1;
tr[u].init(p,a[mid]);
if(l<mid)tr[u].s[0]=build(l,mid-1,u);
if(r>mid)tr[u].s[1]=build(mid+1,r,u);
pushup(u);
return u;
}
void rotate(int x)
{
int y=tr[x].p,z=tr[y].p;
int k=tr[y].s[1]==x;
tr[z].s[tr[z].s[1]==y]=x,tr[x].p=z;
tr[y].s[k]=tr[x].s[k^1],tr[tr[x].s[k^1]].p=y;
tr[x].s[k^1]=y,tr[y].p=x;
pushup(y),pushup(x);
}
void splay(int x,int k)
{
while(tr[x].p!=k)
{
int y=tr[x].p,z=tr[y].p;
if(z!=k)
{
if((tr[z].s[1]==y)^(tr[y].s[1]==x))rotate(x);
else
rotate(y);
}
rotate(x);
}
if(!k)root=x;
}
int get_k(int k)
{
int u=root;
while(u)
{
pushdown(u);
if(tr[tr[u].s[0]].sz>=k)u=tr[u].s[0];
else if(tr[tr[u].s[0]].sz+1==k)return u;
else
k-=tr[tr[u].s[0]].sz+1,u=tr[u].s[1];
}
return -1;
}
void dfs(int u)
{
if(tr[u].s[0])dfs(tr[u].s[0]);
if(tr[u].s[1])dfs(tr[u].s[1]);
save[++cnt]=u;
}
int main()
{
for(int i=1;i<N;i++)save[++cnt]=i;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
a[0]=a[n+1]=-inf;
root=build(0,n+1,0);
while(m--)
{
char op[10];
int pos,k,c;
scanf("%s",op);
if(!strcmp(op,"INSERT"))
{
scanf("%d%d",&pos,&k);
for(int i=0;i<k;i++)scanf("%d",&a[i]);
int l=get_k(pos+1),r=get_k(pos+2);
splay(l,0),splay(r,l);
tr[r].s[0]=build(0,k-1,r);
pushup(r),pushup(l);
}
else if(!strcmp(op,"DELETE"))
{
scanf("%d%d",&pos,&k);
int l=get_k(pos),r=get_k(pos+k+1);
splay(l,0),splay(r,l);
dfs(tr[r].s[0]),tr[r].s[0]=0;
pushup(r),pushup(l);
}
else if(!strcmp(op,"MAKE-SAME"))
{
scanf("%d%d%d",&pos,&k,&c);
int l=get_k(pos),r=get_k(pos+k+1);
splay(l,0),splay(r,l);
auto &p=tr[r].s[0];
tr[p].v=c;
tr[p].same=1;
tr[p].sum=tr[p].sz*c;
if(c>0)tr[p].lmx=tr[p].rmx=tr[p].mx=tr[p].sum;
else
tr[p].lmx=tr[p].rmx=0,tr[p].mx=c;
pushup(r),pushup(l);
}
else if(!strcmp(op,"REVERSE"))
{
scanf("%d%d",&pos,&k);
int l=get_k(pos),r=get_k(pos+k+1);
splay(l,0),splay(r,l);
auto &p=tr[r].s[0];
tr[p].rev^=1;
swap(tr[p].lmx,tr[p].rmx);
swap(tr[p].s[0],tr[p].s[1]);
pushup(r),pushup(l);
}
else if(!strcmp(op,"GET-SUM"))
{
scanf("%d%d",&pos,&k);
int l=get_k(pos),r=get_k(pos+k+1);
splay(l,0),splay(r,l);
printf("%d\n",tr[tr[r].s[0]].sum);
}
else
printf("%d\n",tr[root].mx);
}
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!