JZOJ 2413. 【NOI2005】维护数列
来源:互联网 发布:晕血学生物 知乎 编辑:程序博客网 时间:2024/06/05 22:02
Description
请写一个程序,要求维护一个数列,支持以下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 求出当前数列中和最大的一段子列,并输出最大和
Input
输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
Sample Input
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
Sample Output
-1
10
1
10
Data Constraint
Hint
样例说明请点这里
【数据规模和约定】
你可以认为在任何时刻,数列中至少有1个数。
输入数据一定是正确的,即指定位置的数在数列中一定存在。
50%的数据中,任何时刻数列中最多含有30 000个数;
100%的数据中,任何时刻数列中最多含有500 000个数。
100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
100%的数据中,M ≤20 000,插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Solution
这题真的调试了一万年……
经典的Splay操作,维护子序列的话就维护一下子树前后缀的最大值,在合并到父亲上即可。
Code
#include<cstdio>#include<algorithm>using namespace std;const int N=5e5+3,inf=1e9;int root,tot;int a[N],fa[N],key[N],size[N],s[N][2];int sum[N],c[N],mx[N],pre[N],suf[N],back[N];bool rev[N];inline int read(){ int X=0,w=1; char ch=0; while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();} while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar(); return X*w;}inline void write(int x){ if(x<0) x=-x,putchar('-'); if(x>9) write(x/10); putchar(x%10+'0');}inline int max(int x,int y){ return x>y?x:y;}inline bool pd(int x){ return x==s[fa[x]][1];}inline void newnode(int &v,int val,int p){ if(back[0]) v=back[back[0]--]; else v=++tot; sum[v]=mx[v]=key[v]=val; pre[v]=suf[v]=max(0,val); size[v]=1,fa[v]=p,c[v]=inf; s[v][0]=s[v][1]=rev[v]=0;}inline void reverse(int v){ if(!v) return; swap(s[v][0],s[v][1]); swap(pre[v],suf[v]); rev[v]^=1;}inline void modify(int v,int val){ if(!v) return; sum[v]=size[v]*val,c[v]=key[v]=val; if(val>0) mx[v]=pre[v]=suf[v]=sum[v]; else pre[v]=suf[v]=0,mx[v]=val;}inline void update(int v){ sum[v]=sum[s[v][0]]+sum[s[v][1]]+key[v]; size[v]=size[s[v][0]]+size[s[v][1]]+1; pre[v]=max(pre[s[v][0]],sum[s[v][0]]+key[v]+pre[s[v][1]]); suf[v]=max(suf[s[v][1]],sum[s[v][1]]+key[v]+suf[s[v][0]]); mx[v]=max(0,suf[s[v][0]])+key[v]+max(0,pre[s[v][1]]); if(s[v][0]) mx[v]=max(mx[v],mx[s[v][0]]); if(s[v][1]) mx[v]=max(mx[v],mx[s[v][1]]);}inline void down(int v){ if(rev[v]) { reverse(s[v][0]),reverse(s[v][1]); rev[v]=false; } if(c[v]<inf) { modify(s[v][0],c[v]),modify(s[v][1],c[v]); c[v]=inf; }}inline void build(int &v,int l,int r,int p){ if(l>r) return; int mid=(l+r)>>1; newnode(v,a[mid],p); build(s[v][0],l,mid-1,v); build(s[v][1],mid+1,r,v); update(v);}inline void rotate(int x){ down(x); int y=fa[x],w=pd(x); if(s[y][w]=s[x][w^1]) fa[s[x][w^1]]=y; if(fa[x]=fa[y]) s[fa[y]][pd(y)]=x; s[fa[y]=x][w^1]=y; update(y);}inline void splay(int x,int k){ for(int y;(y=fa[x])^k;rotate(x)) if(fa[y]^k) rotate(pd(x)==pd(y)?y:x); update(x); if(!k) root=x;}inline int kth(int v,int k){ down(v); if(size[s[v][0]]+1==k) return v; if(k<=size[s[v][0]]) return kth(s[v][0],k); return kth(s[v][1],k-size[s[v][0]]-1);}inline void change(int l,int r,int val){ splay(kth(root,l-1),0); splay(kth(root,r+1),root); modify(s[s[root][1]][0],val);}inline int get_sum(int l,int r){ splay(kth(root,l-1),0); splay(kth(root,r+1),root); return sum[s[s[root][1]][0]];}inline void insert(int x,int y){ splay(kth(root,x),0); splay(kth(root,x+1),root); build(s[s[root][1]][0],1,y,s[root][1]); update(s[root][1]),update(root);}inline void travel(int v){ down(v); if(s[v][0]) travel(s[v][0]); back[++back[0]]=v; if(s[v][1]) travel(s[v][1]);}inline void delete_num(int x,int y){ splay(kth(root,x-1),0); splay(kth(root,y+1),root); travel(s[s[root][1]][0]); s[s[root][1]][0]=0; update(s[root][1]),update(root);}inline void flip(int l,int r){ splay(kth(root,l-1),0); splay(kth(root,r+1),root); reverse(s[s[root][1]][0]);}inline int get_max(int l,int r){ splay(kth(root,l-1),0); splay(kth(root,r+1),root); return mx[s[s[root][1]][0]];}inline void print(int v){ down(v); if(s[v][0]) print(s[v][0]); if(key[v]<inf) write(key[v]),putchar(' '); if(s[v][1]) print(s[v][1]);}int main(){ int n=read(),m=read(); a[1]=a[n+2]=-inf,c[0]=inf; for(int i=2;i<=n+1;i++) a[i]=read(); build(root,1,n+2,0); while(m--) { char ch=getchar(); while(ch!='X' && ch!='G' && ch!='V' && ch!='I' && ch!='D' && ch!='K') ch=getchar(); if(ch=='K')//MAKE-SAME { getchar(),getchar(); int x=read()+1,y=x+read()-1; change(x,y,read()); }else if(ch=='G')//GET-SUM { getchar(),getchar(),getchar(); int x=read()+1,y=x+read()-1; write(get_sum(x,y)),putchar('\n'); }else if(ch=='I')//INSERT { int x=read()+1,y=read(); for(int i=1;i<=y;i++) a[i]=read(); insert(x,y); }else if(ch=='D')//DELETE { int x=read()+1,y=x+read()-1; delete_num(x,y); }else if(ch=='V')//REVERSE { int x=read()+1,y=x+read()-1; flip(x,y); }else if(ch=='X')//MAX-SUM { write(get_max(2,size[root]-1)),putchar('\n'); scanf("\n"); } } return 0;}
- JZOJ 2413. 【NOI2005】维护数列
- 【NOI2005】【JZOJ 2413】【BZOJ 1500】维护数列
- 【noi2005】维护数列
- [NOI2005] 维护数列 sequence
- 【NOI2005】【splay】维护数列
- 数列维护 NOI2005
- 【SPLAY】NOI2005 维护数列
- 【noi2005】维护数列
- NOI2005维护数列
- noi2005维护数列 splay
- JZOJ2413. 【NOI2005】维护数列
- 【NOI2005】维护数列
- 【NOI2005】维护数列
- [NOI2005] 维护数列
- [题解]NOI2005 维护数列
- noi2005维护数列
- 【NOI2005】维护数列(BSOI2246)
- JZOJ2413 【NOI2005】维护数列
- [DP 倍增Floyd] LOJ#539.「LibreOJ NOIP Round #1」旅游路线
- Chrome 浏览器客户端调试大全
- 在Vue-cli里基于axios封装复用请求
- caffe中的SoftmaxLoss层
- wxWidgets嵌入CEF3,并实现JavaScript调用C++代码
- JZOJ 2413. 【NOI2005】维护数列
- 骨牌铺方格
- sql优化
- 类的特点--继承
- VS2010+OPENCV3.0配置备忘
- 机器学习算法推荐
- 巴斯卡三角形(杨辉三角)(c/python)
- atcoder AtCoder Regular Contest 084 D
- Spring Boot:(一)快速入门