955. 维护数列

题目链接

955. 维护数列

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

image

输入格式

1 行包含两个数 NMN 表示初始时数列中数的个数,M 表示要进行的操作数目。

2 行包含 N 个数字,描述初始时的数列。

以下 M 行,每行一条命令,格式参见问题描述中的表格。

输出格式

对于输入数据中的 GET-SUMMAX-SUM 操作,向输出文件依次打印结果,每个答案(数字)占一行。

数据范围与约定

你可以认为在任何时刻,数列中至少有 1 个数。

输入数据一定是正确的,即指定位置的数在数列中一定存在。

50% 的数据中,任何时刻数列中最多含有 30000 个数;100% 的数据中,任何时刻数列中最多含有 500000 个数。

100% 的数据中,任何时刻数列中任何一个数字均在 [1000,1000] 内。

100% 的数据中,M20000,插入的数字总数不超过 4000000 个,输入文件大小不超过 20 MBytes

输入样例:

9 8 2 -6 3 5 1 -5 -3 6 3 GET-SUM 5 4 MAX-SUM INSERT 8 3 -5 7 2 DELETE 12 1 MAKE-SAME 3 3 2 REVERSE 3 6 GET-SUM 5 4 MAX-SUM

输出样例:

-1 10 1 10

解题思路

splay,动态开点,内存回收机制

开两个懒标记:same,rev,表示修改和翻转标记,这两个标记其一的改变不会造成另一个的变化,可用常见数据结构维护,而操作涉及 操作,线段树不好维护,而 splay 很好操作,即将对应区间操作转化为某一棵子树的操作,而由于插入的数据很大,为了避免超内存,可引入内存回收机制,即进行删除操作时可以将删除的节点编号回收。其他操作同线段树

  • 时间复杂度:O((n+m)×logn)

代码

// Problem: 维护数列 // Contest: AcWing // URL: https://www.acwing.com/problem/content/957/ // Memory Limit: 256 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #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__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16483604.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示