P2042 [NOI2005] 维护数列
P2042 [NOI2005] 维护数列
请写一个程序,要求维护一个数列,支持以下
编号 | 名称 | 格式 | 说明 |
---|---|---|---|
1 | 插入 | 在当前数列的第 |
|
2 | 删除 | 从当前数列的第 |
|
3 | 修改 | 从当前数列的第 |
|
4 | 翻转 | 取出从当前数列的第 |
|
5 | 求和 | 计算从当前数列的第 |
|
6 | 求最大子列和 | 求出当前数列中和最大的一段子列,并输出最大和 |
数据规模与约定
- 对于
的数据,任何时刻数列中最多含有 个数,任何时刻数列中任何一个数字均在 内, ,插入的数字总数不超过 。
Solution:
如果没有最大子段和的话那么这题就是一个普通的平衡树板子,但是有了这个诡异的最大字段和我们就需要在pushup的时候尤为小心
这就是你一道紫题写一个早上的理由?(╯°Д°)╯︵ ┻━┻
由于这题我们要用平衡树维护最大子段和,所以我们需要在 pushup 时加上当前节点的贡献
然后这题按题意维护平衡树即可。
还有就是这题虽然最多只有 【数据删除】 上回收一下
然后这题就愉快(存疑)的做完了
Code:
#include<bits/stdc++.h> const int N=5e5+5; using namespace std; inline int Max(int x,int y){return x>y ? x : y;} int n,m,rt,cnt; queue<int> Q; int A[N]; //FHQ_Treap: struct Tree{ int ls,rs,val,lmx,rmx,mx,sum,tag,rev,siz,pri; }t[N]; inline int rd(){return rand()*rand()+17;} inline int Node(int val){int res=Q.front();Q.pop();t[res]={0,0,val,Max(0,val),Max(0,val),val,val,N,0,1,rd()};return res;} int flag=0; inline void pushup(int x) { int ls=t[x].ls,rs=t[x].rs; t[x].siz=t[ls].siz+t[rs].siz+1; t[x].sum=t[ls].sum+t[rs].sum+t[x].val; t[x].lmx=Max(Max(t[ls].lmx,t[ls].sum+t[rs].lmx+t[x].val),0); t[x].rmx=Max(Max(t[rs].rmx,t[rs].sum+t[ls].rmx+t[x].val),0); t[x].mx=Max(t[ls].rmx+t[rs].lmx,0)+t[x].val; if(ls)t[x].mx=Max(t[x].mx,t[ls].mx); if(rs)t[x].mx=Max(t[x].mx,t[rs].mx); } inline void rev(int x) { swap(t[x].lmx,t[x].rmx); t[x].rev^=1;swap(t[x].ls,t[x].rs); } inline void change(int x,int tag) { t[x].sum=t[x].siz*tag; t[x].lmx=t[x].rmx=max(0,t[x].sum); t[x].mx=max(t[x].sum,tag); t[x].val=t[x].tag=tag; } inline void pushdown(int x) { int ls=t[x].ls,rs=t[x].rs,tag=t[x].tag; if(t[x].rev) { if(ls)rev(ls); if(rs)rev(rs); t[x].rev=0; } if(t[x].tag!=N) { if(ls)change(ls,tag); if(rs)change(rs,tag); t[x].tag=N; } return ; } inline void splite(int x,int &a,int &b,int k) { if(!x){a=b=0;return ;} int tmp=t[t[x].ls].siz+1; pushdown(x); if(k>=tmp){a=x;splite(t[x].rs,t[x].rs,b,k-tmp);} else {b=x;splite(t[x].ls,a,t[x].ls,k);} pushup(x); } inline int merge(int x,int y) { if(!x||!y)return x|y; pushdown(x);pushdown(y); if(t[x].pri<t[y].pri){t[x].rs=merge(t[x].rs,y);pushup(x);return x;} else {t[y].ls=merge(x,t[y].ls);pushup(y);return y;} } void insert(int pos) { int a,b; splite(rt,a,b,pos); for(int i=1;i<=A[0];i++) { a=merge(a,Node(A[i])); } rt=merge(a,b); A[0]=0; } inline void recycle(int x){if(!x)return ;Q.push(x);recycle(t[x].ls);recycle(t[x].rs);} void del(int x,int tot) { int a,b,c; splite(rt,a,b,x-1); splite(b,b,c,tot); recycle(b); rt=merge(a,c); } void same(int x,int tot,int tag) { int a,b,c; splite(rt,a,b,x-1); splite(b,b,c,tot); change(b,tag); rt=merge(merge(a,b),c); } void reverse(int x,int tot) { int a,b,c; splite(rt,a,b,x-1); splite(b,b,c,tot); rev(b); rt=merge(merge(a,b),c); } void sum(int x,int tot) { int a,b,c; splite(rt,a,b,x-1); splite(b,b,c,tot); printf("%d\n",t[b].sum); rt=merge(merge(a,b),c); } char s[N]; void work() { cin>>n>>m; for(int i=N-1;i;i--)Q.push(i); for(int i=1;i<=n;i++) { scanf("%d",&A[++A[0]]); } insert(0); int pos,tot,tag; for(int i=1;i<=m;i++) { scanf("%s",s); if(s[0]=='M'&&s[2]=='X') { printf("%d\n",t[rt].mx);continue; } scanf("%d%d",&pos,&tot); if(s[0]=='I') { for(int i=1;i<=tot;i++)scanf("%d",&A[++A[0]]); insert(pos);continue; } if(s[0]=='D') { del(pos,tot); } if(s[0]=='M') { scanf("%d",&tag); same(pos,tot,tag); } if(s[0]=='R') { reverse(pos,tot); } if(s[0]=='G') { sum(pos,tot); } } } int main() { srand(998244353); //freopen("P2042_2.in","r",stdin);freopen("P2042.out","w",stdout); work(); return 0; }