您的位置:首页 > 运维架构

[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的各种操作

建议阅读《伸展树的基本操作与应用》

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构 splay