[NOI2005] 维护数列
2016-11-25 23:28
288 查看
[NOI2005] 维护数列
时间限制:3 s 内存限制:256 MB
【问题描述】
请写一个程序,要求维护一个数列,支持以下 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
求出当前数列中和最大的一段子列,并输出最大和
【输入格式】
输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M表示要进行的操作数目。
第 2 行包含 N 个数字,描述初始时的数列。
以下 M 行,每行一条命令,格式参见问题描述中的表格。
【输出格式】
对于输入数据中的 GET-SUM 和 MAX-SUM 操作,向输出文件依次打印结果,每个答案(数字)占一行。
【输入样例】
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
【样例说明】
初始时,我们拥有数列 2 -6 3 5 1 -5 -3 6 3
执行操作 GET-SUM 5 4,表示求出数列中从第 5 个数开始连续 4 个数字之和,1+(-5)+(-3)+6 = -1:
2 -6 3 5 1 -5 -3 6 3
执行操作 MAX-SUM,表示要求求出当前数列中最大的一段和,应为 3+5+1+(-5)+(-3)+6+3 = 10:
2 -6 3 5 1 -5 -3 6 3
执行操作 INSERT 8 3 -5 7 2,即在数列中第 8 个数字后插入-5 7 2,
2 -6 3 5 1 -5 -3 6 -5 7 2 3
执行操作 DELETE 12 1,表示删除第 12 个数字,即最后一个:
2 -6 3 5 1 -5 -3 6 -5 7 2
执行操作 MAKE-SAME 3 3 2,表示从第 3 个数开始的 3 个数字,统一修改为 2:
2 -6 3 5 1 -5 -3 6 -5 7 2
改为
2 -6 2 2 2 -5 -3 6 -5 7 2
执行操作 REVERSE 3 6,表示取出数列中从第 3 个数开始的连续 6 个数:
2 -6 2 2 2 -5 -3 6 -5 7 2
如上所示的灰色部分 2 2 2 -5 -3 6,翻转后得到 6 -3 -5 2 2 2,并放回原来位置:
2 -6 6 -3 -5 2 2 2 -5 7 2
最后执行 GET-SUM 5 4 和 MAX-SUM,不难得到答案 1 和 10。
2 -6 6 -3 -5 2 2 2 -5 7 2
【评分方法】
本题设有部分分,对于每一个测试点:
如果你的程序能在输出文件正确的位置上打印 GET-SUM 操作的答案,你可以得到该测试点 60%的分数;
如果你的程序能在输出文件正确的位置上打印 MAX-SUM 操作的答案,你可以得到该测试点 40%的分数;
以上两条的分数可以叠加,即如果你的程序正确输出所有 GET-SUM 和MAX-SUM 操作的答案,你可以得到该测试点 100%的分数。
请注意:如果你的程序只能正确处理某一种操作,请确定在输出文件正确的位置上打印结果,即必须为另一种操作留下对应的行,否则我们不保证可以正确评分。
【数据规模和约定】
你可以认为在任何时刻,数列中至少有 1 个数。
输入数据一定是正确的,即指定位置的数在数列中一定存在。
50%的数据中,任何时刻数列中最多含有 30 000 个数;
100%的数据中,任何时刻数列中最多含有 500 000 个数。
100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 个,输入文件大小不超过 20MBytes。
splay的各种操作
建议阅读《伸展树的基本操作与应用》
时间限制:3 s 内存限制:256 MB
【问题描述】
请写一个程序,要求维护一个数列,支持以下 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
求出当前数列中和最大的一段子列,并输出最大和
【输入格式】
输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M表示要进行的操作数目。
第 2 行包含 N 个数字,描述初始时的数列。
以下 M 行,每行一条命令,格式参见问题描述中的表格。
【输出格式】
对于输入数据中的 GET-SUM 和 MAX-SUM 操作,向输出文件依次打印结果,每个答案(数字)占一行。
【输入样例】
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
【样例说明】
初始时,我们拥有数列 2 -6 3 5 1 -5 -3 6 3
执行操作 GET-SUM 5 4,表示求出数列中从第 5 个数开始连续 4 个数字之和,1+(-5)+(-3)+6 = -1:
2 -6 3 5 1 -5 -3 6 3
执行操作 MAX-SUM,表示要求求出当前数列中最大的一段和,应为 3+5+1+(-5)+(-3)+6+3 = 10:
2 -6 3 5 1 -5 -3 6 3
执行操作 INSERT 8 3 -5 7 2,即在数列中第 8 个数字后插入-5 7 2,
2 -6 3 5 1 -5 -3 6 -5 7 2 3
执行操作 DELETE 12 1,表示删除第 12 个数字,即最后一个:
2 -6 3 5 1 -5 -3 6 -5 7 2
执行操作 MAKE-SAME 3 3 2,表示从第 3 个数开始的 3 个数字,统一修改为 2:
2 -6 3 5 1 -5 -3 6 -5 7 2
改为
2 -6 2 2 2 -5 -3 6 -5 7 2
执行操作 REVERSE 3 6,表示取出数列中从第 3 个数开始的连续 6 个数:
2 -6 2 2 2 -5 -3 6 -5 7 2
如上所示的灰色部分 2 2 2 -5 -3 6,翻转后得到 6 -3 -5 2 2 2,并放回原来位置:
2 -6 6 -3 -5 2 2 2 -5 7 2
最后执行 GET-SUM 5 4 和 MAX-SUM,不难得到答案 1 和 10。
2 -6 6 -3 -5 2 2 2 -5 7 2
【评分方法】
本题设有部分分,对于每一个测试点:
如果你的程序能在输出文件正确的位置上打印 GET-SUM 操作的答案,你可以得到该测试点 60%的分数;
如果你的程序能在输出文件正确的位置上打印 MAX-SUM 操作的答案,你可以得到该测试点 40%的分数;
以上两条的分数可以叠加,即如果你的程序正确输出所有 GET-SUM 和MAX-SUM 操作的答案,你可以得到该测试点 100%的分数。
请注意:如果你的程序只能正确处理某一种操作,请确定在输出文件正确的位置上打印结果,即必须为另一种操作留下对应的行,否则我们不保证可以正确评分。
【数据规模和约定】
你可以认为在任何时刻,数列中至少有 1 个数。
输入数据一定是正确的,即指定位置的数在数列中一定存在。
50%的数据中,任何时刻数列中最多含有 30 000 个数;
100%的数据中,任何时刻数列中最多含有 500 000 个数。
100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 个,输入文件大小不超过 20MBytes。
splay的各种操作
建议阅读《伸展树的基本操作与应用》
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define LL long long #define seq tr[tr[root].ch[1]].ch[0] #define INF (1<<29) using namespace std; const int N=510000; struct node{ int ch[2],fa,size,v,ll,rr,mm,tt;bool rev,lz; }; int n,m,w ; struct Splay{ node tr ;int tot,tot2,root,s ; void update(int x){int l=tr[x].ch[0],r=tr[x].ch[1];tr[x].size=tr[l].size+tr[r].size+1;tr[x].tt=tr[l].tt+tr[r].tt+tr[x].v;tr[x].ll=max(tr[l].ll,tr[l].tt+tr[x].v+max(0,tr[r].ll));tr[x].rr=max(tr[r].rr,tr[r].tt+tr[x].v+max(0,tr[l].rr));tr[x].mm=max(max(tr[l].mm,tr[r].mm),tr[x].v+max(0,tr[l].rr)+max(0,tr[r].ll));} void zig(int x){int y=tr[x].fa;tr[y].ch[0]=tr[x].ch[1];if(tr[x].ch[1])tr[tr[x].ch[1]].fa=y;tr[x].ch[1]=y;tr[x].fa=tr[y].fa;tr[y].fa=x;if(tr[x].fa){if(tr[tr[x].fa].ch[0]==y) tr[tr[x].fa].ch[0]=x;else tr[tr[x].fa].ch[1]=x;}update(y);} void zag(int x){int y=tr[x].fa;tr[y].ch[1]=tr[x].ch[0];if(tr[x].ch[0])tr[tr[x].ch[0]].fa=y;tr[x].ch[0]=y;tr[x].fa=tr[y].fa;tr[y].fa=x;if(tr[x].fa){if(tr[tr[x].fa].ch[0]==y) tr[tr[x].fa].ch[0]=x;else tr[tr[x].fa].ch[1]=x;}update(y);} void splay(int x,int target){while(tr[x].fa!=target){int y=tr[x].fa;if(tr[y].fa==target){tr[y].ch[0]==x?zig(x):zag(x);} else {if(tr[tr[y].fa].ch[0]==y){if(tr[y].ch[0]==x) {zig(y);zig(x);}else {zag(x);zig(x);}}else {if(tr[y].ch[1]==x) {zag(y);zag(x);}else {zig(x);zag(x);}}}}update(x);if(!target) root=x;} void downlab(int x){int l=tr[x].ch[0],r=tr[x].ch[1],ww=tr[x].v;if(tr[x].lz){if(l) {down(l,ww);}if(r) {down(r,ww);}tr[x].lz=0;}if(tr[x].rev){if(l) {rever(l);}if(r){rever(r);}tr[x].rev=0;}} void search(int x,int target){int y=root;while(1){downlab(y);if(x==tr[tr[y].ch[0]].size+1) break;if(x<=tr[tr[y].ch[0]].size){y=tr[y].ch[0];}else{ x-=(tr[tr[y].ch[0]].size+1); y=tr[y].ch[1]; } }splay(y,target); } void newnode(int &x,int pnt,int val){ x=tot2?s[tot2--]:++tot;tr[x].v=tr[x].tt=tr[x].ll=tr[x].mm=tr[x].rr=val; tr[x].rev=tr[x].lz=tr[x].ch[0]=tr[x].ch[1]=0; tr[x].fa=pnt;tr[x].size=1; } void init(int n){tr[0].mm=tr[0].ll=tr[0].rr=-INF; newnode(root,0,0); newnode(tr[root].ch[1],root,0); build(seq,tr[root].ch[1],1,n); update(tr[root].ch[1]); update(root); } void build(int &x,int pnt,int l,int r){ if(l>r) return; int mid=(l+r)>>1;newnode(x,pnt,w[mid]); build(tr[x].ch[0],x,l,mid-1); build(tr[x].ch[1],x,mid+1,r); update(x); } void insert(int pos,int num){ search(pos,0);search(pos+1,root); build(seq,tr[root].ch[1],1,num); update(tr[root].ch[1]); update(root); } void eraser(int x){ if(!x) return;s[++tot2]=x; eraser(tr[x].ch[0]);eraser(tr[x].ch[1]); } void del(int l,int r){ search(l,0);search(r+2,root); eraser(seq); tr[tr[tr[root].ch[1]].ch[0]].fa=0;tr[tr[root].ch[1]].ch[0]=0; update(tr[root].ch[1]);update(root); } void down(int x,int c){ if(!x) return;tr[x].lz=1;tr[x].v=c; tr[x].tt=c*tr[x].size;tr[x].mm=tr[x].ll=tr[x].rr=c>0?tr[x].tt:c; } void change(int l,int r,int c){ search(l,0);search(r+2,root);down(seq,c); update(tr[root].ch[1]);update(root); } void rever(int x){ if(!x) return;swap(tr[x].ch[0],tr[x].ch[1]); tr[x].rev^=1;swap(tr[x].ll,tr[x].rr); } void turn(int l,int r){ search(l,0);search(r+2,root); rever(seq); } void print(int x){ printf("Instructions of x:%d %d %d %d %d %d %d %d %d\n",tr[x].ch[0],tr[x].ch[1],tr[x].fa,tr[x].ll,tr[x].rr,tr[x].mm,tr[x].tt,tr[x].size,tr[x].v); } void Ask_Max(int sum){ search(1,0);search(sum+2,root);update(seq); printf("%d\n",max(tr[seq].mm,max(tr[seq].ll,tr[seq].rr))); } void Ask_Sum(int l,int r){ search(l,0);search(r+2,root); printf("%d\n",tr[seq].tt); } }Tree; char s[20]; int read(){ char ch=getchar();int f=1,x=0; while(ch>'9'||ch<'0') {if(ch=='-') f=-1;ch=getchar();} while(ch<='9'&&ch>='0') {x=x*10+ch-'0';ch=getchar();} return f*x; } int main(){ freopen("seq2005.in","r",stdin); freopen("seq2005.out","w",stdout); n=read();m=read(); for(int i=1;i<=n;i++) w[i]=read();Tree.init(n); for(int i=1,be,Q,W;i<=m;i++){ scanf("%s",s+1); if(s[1]=='I'){be=read();Q=read();n+=Q;for(int j=1;j<=Q;j++) w[j]=read();Tree.insert(be+1,Q);} if(s[1]=='D'){be=read();Q=read();n-=Q;Tree.del(be,be+Q-1);} if(s[1]=='M'&&s[3]=='K'){be=read();Q=read();W=read();Tree.change(be,be+Q-1,W);} if(s[1]=='M'&&s[3]=='X'){Tree.Ask_Max(n);} if(s[1]=='G'){be=read();Q=read();Tree.Ask_Sum(be,be+Q-1);} if(s[1]=='R'){be=read();Q=read();Tree.turn(be,be+Q-1);} } fclose(stdin); fclose(stdout); return 0; }
相关文章推荐
- bsoj 2246 【NOI2005】维护数列(splay解法)
- 【NOI2005】【JZOJ 2413】【BZOJ 1500】维护数列
- NOI2005维护数列
- [您有新的未分配科技点] 无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )
- CODEVS-1758-维护数列-NOI2005-splay
- JZOJ2413 【NOI2005】维护数列
- noi 2005 维护数列 平衡树
- noi2005维护数列
- 洛谷P2042 [NOI2005]维护数列
- [NOI 2005] 维护数列 splay
- JZOJ 2413. 【NOI2005】维护数列
- 数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列
- 【jzoj2413】【NOI2005】【维护数列】【splay】
- BZOJ 1500([NOI2005]维修数列-Splay的数列维护)
- 【NOI2005】【splay】维护数列
- JZOJ2413. 【NOI2005】维护数列
- 【bzoj1500】 noi2005—维护数列
- 无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )
- 洛谷P2042 [NOI2005]维护数列
- 【NOI 2005】【JZOJ 2413】维护数列 平衡树操作模板题