1500: [NOI2005]维修数列

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 6263  Solved: 1879
[Submit][Status]

Description

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

HINT

Source

【数据规模和约定】
你可以认为在任何时刻,数列中至少有 1 个数。
输入数据一定是正确的,即指定位置的数在数列中一定存在。
50%的数据中,任何时刻数列中最多含有 30 000 个数;
100%的数据中,任何时刻数列中最多含有 500 000 个数。
100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 个,输入文件
大小不超过 20MBytes。

题解:

原来看起来望而生畏啊,现在看着也不觉得什么。。。

这里面难度最大的操作是:区间修改成某个定值。好像这块我原来在写线段树的时候就没学会。。。

貌似splay的自顶向下的东西全都加到pushdown里面就可以,自底向上的东西全部加到pushup里就可以?

ms是这样的。。。

代码的缩行技巧值得思考,我想了大半天。。。

(ps:其实我觉得这题 1000*500000=50亿是可以爆longint的,所以应该用int64,但既然longint可以过那我就懒得改了

不过考试的话为了保险我还是会用int64de。。。)

代码:

1.hzwer(好整齐的说。。。)

 #include<cstdio>
#include<iostream>
#define N 1000005
#define inf 1000000000
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,m,sz,rt;
int fa[N],c[N][],id[N];
int a[N],lmx[N],rmx[N],mx[N],size[N],rec[N],v[N],sum[N];
bool tag[N],rev[N];
void pushup(int k)
{
int l=c[k][],r=c[k][];
size[k]=size[l]+size[r]+;
sum[k]=sum[l]+sum[r]+v[k];
mx[k]=max(mx[l],mx[r]);
mx[k]=max(mx[k],rmx[l]+v[k]+lmx[r]);
lmx[k]=max(lmx[l],sum[l]+v[k]+lmx[r]);
rmx[k]=max(rmx[r],sum[r]+v[k]+rmx[l]);
}
void pushdown(int k)
{
int l=c[k][],r=c[k][];
if(tag[k])
{
tag[k]=rev[k]=;
if(l){tag[l]=;v[l]=v[k];sum[l]=v[k]*size[l];}
if(r){tag[r]=;v[r]=v[k];sum[r]=v[k]*size[r];}
if(v[k]>=)
{
if(l)lmx[l]=rmx[l]=mx[l]=sum[l];
if(r)lmx[r]=rmx[r]=mx[r]=sum[r];
}
else
{
if(l)lmx[l]=rmx[l]=,mx[l]=v[k];
if(r)lmx[r]=rmx[r]=,mx[r]=v[k];
}
}
if(rev[k])
{
rev[k]^=;rev[l]^=;rev[r]^=;
swap(lmx[l],rmx[l]);swap(lmx[r],rmx[r]);
swap(c[l][],c[l][]);swap(c[r][],c[r][]);
pushup(k);
}
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l,r;
if(c[y][]==x)l=;else l=;r=l^;
if(y==k)k=x;
else {if(c[z][]==y)c[z][]=x;else c[z][]=x;}
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x,int &k)
{
while(x!=k)
{
int y=fa[x],z=fa[y];
if(y!=k)
{
if(c[y][]==x^c[z][]==y)rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
void build(int l,int r,int f)
{
if(l>r)return;
int now=id[l],last=id[f];
if(l==r)
{
v[now]=mx[now]=sum[now]=a[l];
fa[now]=last;size[now]=;
if(a[l]>=)lmx[now]=rmx[now]=a[l];
else lmx[now]=rmx[now]=;
if(l<f)c[last][]=now;
else c[last][]=now;
return;
}
int mid=(l+r)>>;now=id[mid];
build(l,mid-,mid);build(mid+,r,mid);
v[now]=a[mid];fa[now]=last;pushup(now);
if(mid<f)c[last][]=now;
else c[last][]=now;
}
int find(int k,int rk)
{
if(tag[k]||rev[k])pushdown(k);
int l=c[k][],r=c[k][];
if(size[l]+==rk)return k;
else if(size[l]>=rk)return find(l,rk);
else return find(r,rk-size[l]-);
}
void reclaim(int k)
{
if(!k)return;
int l=c[k][],r=c[k][];
reclaim(l);reclaim(r);
fa[k]=c[k][]=c[k][]=;
tag[k]=rev[k]=;
rec[++rec[]]=k;
}
void ins(int k,int tot)
{
int x,y,z;
for(int i=;i<=tot;i++)
{
a[i]=read();
if(rec[])id[i]=rec[rec[]--];
else id[i]=++sz;
}
build(,tot,);
z=id[(tot+)>>];
x=find(rt,k+);y=find(rt,k+);
splay(x,rt);splay(y,c[x][]);
c[y][]=z;fa[z]=y;
pushup(y);pushup(x);
}
void dele(int k,int tot)
{
int x,y,z;
x=find(rt,k);y=find(rt,k+tot+);
splay(x,rt);splay(y,c[x][]);
z=c[y][];reclaim(z);c[y][]=;
pushup(y);pushup(x);
}
void solve_change(int k,int val)
{
v[k]=val;tag[k]=;
sum[k]=v[k]*size[k];
if(val>=)lmx[k]=rmx[k]=mx[k]=sum[k];
else lmx[k]=rmx[k]=,mx[k]=v[k];
}
void solve_rever(int k)
{
if(tag[k])return;
rev[k]^=;
swap(c[k][],c[k][]);
swap(lmx[k],rmx[k]);
}
void change(int k,int tot,int val)
{
int x,y,z;
x=find(rt,k);y=find(rt,k+tot+);
splay(x,rt);splay(y,c[x][]);
z=c[y][];
solve_change(z,val);
pushup(y);pushup(x);
}
void rever(int k,int tot)
{
int x,y,z;
x=find(rt,k);y=find(rt,k+tot+);
splay(x,rt);splay(y,c[x][]);
z=c[y][];
solve_rever(z);
pushup(y);pushup(x);
}
void query(int k,int tot)
{
int x,y,z;
x=find(rt,k);y=find(rt,k+tot+);
splay(x,rt);splay(y,c[x][]);
z=c[y][];
printf("%d\n",sum[z]);
}
int main()
{
n=read();m=read();
mx[]=-inf;
a[]=a[n+]=-inf;
for(int i=;i<=n;i++)
a[i+]=read();
for(int i=;i<=n+;i++)
id[i]=i;
build(,n+,);
rt=(n+)>>;sz=n+;
char s[];
int k,tot,val;
for(int i=;i<=m;i++)
{
scanf("%s",s);
switch(s[])
{
case 'I':k=read();tot=read();ins(k,tot);break;
case 'D':k=read();tot=read();dele(k,tot);break;
case 'M':
if(s[]=='K')
{k=read();tot=read();val=read();change(k,tot,val);}
else printf("%d\n",mx[rt]);
break;
case 'R':k=read();tot=read();rever(k,tot);break;
case 'G':k=read();tot=read();query(k,tot);break;
}
}
return ;
}

2.mine

 {$inline on}
{$M 1000000000,0,maxlongint}
const maxn=+;
var s,sum,v,lm,rm,mx,fa,sta,id,a:array[..maxn] of longint;
rev,tag:array[..maxn] of boolean;
c:array[..maxn,..] of longint;
i,n,m,x,y,z,top,rt,now,num:longint;
ch:char;
procedure swap(var x,y:longint);inline;
var t:longint;
begin
t:=x;x:=y;y:=t;
end;
function max(x,y:longint):longint;inline;
begin
if x>y then exit(x) else exit(y);
end;
procedure pushup(x:longint);inline;
var l,r:longint;
begin
l:=c[x,];r:=c[x,];
s[x]:=s[l]+s[r]+;
sum[x]:=sum[l]+sum[r]+v[x];
lm[x]:=max(lm[l],sum[l]+v[x]+lm[r]);
rm[x]:=max(rm[r],sum[r]+v[x]+rm[l]);
mx[x]:=max(rm[l]+lm[r]+v[x],max(mx[l],mx[r]));
end;
procedure change(x,y:longint);inline;
begin
if x= then exit;
tag[x]:=true;
v[x]:=y;sum[x]:=s[x]*y;
if v[x]>= then
begin
lm[x]:=sum[x];rm[x]:=sum[x];mx[x]:=sum[x];
end
else
begin
lm[x]:=;rm[x]:=;mx[x]:=v[x];
end;
end;
procedure rever(x:longint);inline;
begin
if (tag[x]) or (x=) then exit;
rev[x]:=not(rev[x]);
swap(c[x,],c[x,]);
swap(lm[x],rm[x]);
end;
procedure pushdown(x:longint);inline;
var l,r:longint;
begin
l:=c[x,];r:=c[x,];
if tag[x] then
begin
tag[x]:=false;rev[x]:=false;
change(l,v[x]);change(r,v[x]);
end;
if rev[x] then
begin
rev[x]:=false;
rever(l);rever(r);
pushup(x);
end;
end;
procedure rotate(x:longint;var k:longint);inline;
var y,z,l,r:longint;
begin
y:=fa[x];z:=fa[y];
l:=ord(c[y,]=x);r:=l xor ;
if y=k then k:=x else c[z,ord(c[z,]=y)]:=x;
fa[x]:=z;fa[y]:=x;fa[c[x,r]]:=y;
c[y,l]:=c[x,r];c[x,r]:=y;
pushup(y);pushup(x);
end;
procedure splay(x:longint;var k:longint);inline;
var y,z:longint;
begin
while x<>k do
begin
y:=fa[x];z:=fa[y];
if y<>k then
if (c[z,]=y) xor (c[y,]=x) then rotate(x,k)
else rotate(y,k);
rotate(x,k);
end;
end;
function find(x,rank:longint):longint;inline;
var l,r:longint;
begin
if (tag[x]) or (rev[x]) then pushdown(x);
l:=c[x,];r:=c[x,];
if s[l]+=rank then exit(x)
else if s[l]>=rank then exit(find(l,rank))
else exit(find(r,rank-s[l]-));
end;
procedure build(l,r,f:longint);inline;
var x,y,z,mid:longint;
begin
if l>r then exit;
mid:=(l+r)>>;
x:=id[mid];y:=id[f];
v[x]:=a[mid];
c[y,ord(mid>f)]:=x;fa[x]:=y;
if l=r then
begin
s[x]:=;sum[x]:=v[x];mx[x]:=v[x];
if v[x]>= then z:=v[x] else z:=;
lm[x]:=z;rm[x]:=z;
exit;
end;
build(l,mid-,mid);build(mid+,r,mid);
pushup(x);
end;
procedure split(l,r:longint;var x,y:longint);inline;
begin
x:=find(rt,l);y:=find(rt,r);
splay(x,rt);splay(y,c[x,]);
end;
procedure insert;inline;
var i,x,y:longint;
begin
for i:= to n do
begin
read(a[i]);
id[i]:=sta[top];dec(top);
end;
readln;
build(,n,);
split(now+,now+,x,y);
z:=id[(n+)>>];
c[y,]:=z;fa[z]:=y;
pushup(y);pushup(x);
end;
procedure delete(x:longint);inline;
begin
if x= then exit;
delete(c[x,]);
delete(c[x,]);
inc(top);
sta[top]:=x;c[x,]:=;c[x,]:=;fa[x]:=;
rev[x]:=false;tag[x]:=false;
end;
procedure main;
begin
readln(n,m);
a[]:=-;a[n+]:=-;mx[]:=-;
for i:= to n+ do read(a[i]);readln;
for i:= to n+ do id[i]:=i;
build(,n+,);rt:=(n+)>>;
for i:=maxn downto n+ do sta[maxn+-i]:=i;
top:=maxn-n-;
fillchar(tag,sizeof(tag),false);
fillchar(rev,sizeof(rev),false);
for i:= to m do
begin
read(ch);
case ch of
'I':begin
while ch<>' ' do read(ch);
read(now,n);
insert;
end;
'D':begin
while ch<>' ' do read(ch);
readln(now,n);
split(now,now+n+,x,y);
delete(c[y,]);c[y,]:=;
pushup(y);pushup(x);
end;
'R':begin
while ch<>' ' do read(ch);
readln(now,n);
split(now,now+n+,x,y);
rever(c[y,]);
pushup(y);pushup(x);
end;
'M':begin
read(ch);read(ch);
if ch='K' then
begin
while ch<>' ' do read(ch);
readln(now,n,num);
split(now,now+n+,x,y);
change(c[y,],num);
pushup(y);pushup(x);
end
else
begin
readln;
writeln(mx[rt]);
end;
end;
'G':begin
while ch<>' ' do read(ch);
readln(now,n);
split(now,now+n+,x,y);
writeln(sum[c[y,]]);
end;
end;
end;
end;
begin
assign(input,'input.txt');assign(output,'output.txt');
reset(input);rewrite(output);
main;
close(input);close(output);
end.

吐槽一下:wikioi网又慢,机子又慢,时限还短

vijos网快,机子快,时限长

bzoj网快,机子时快时慢,时限短

NOI2005维护数列的更多相关文章

  1. 数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列

    339. [NOI2005] 维护数列 时间限制:3 s   内存限制:256 MB [问题描述] 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际 ...

  2. [NOI2005] 维护数列

    [NOI2005] 维护数列 题目 传送门 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 操作编号 输入文件中的格式 说明 1 ...

  3. P2042 [NOI2005]维护数列 && Splay区间操作(四)

    到这里 \(A\) 了这题, \(Splay\) 就能算入好门了吧. 今天是个特殊的日子, \(NOI\) 出成绩, 大佬 \(Cu\) 不敢相信这一切这么快, 一下子机房就只剩我和 \(zrs\) ...

  4. 洛谷 P2042 [NOI2005]维护数列-Splay(插入 删除 修改 翻转 求和 最大的子序列)

    因为要讲座,随便写一下,等讲完有时间好好写一篇splay的博客. 先直接上题目然后贴代码,具体讲解都写代码里了. 参考的博客等的链接都贴代码里了,有空再好好写. P2042 [NOI2005]维护数列 ...

  5. P2042 [NOI2005]维护数列[splay或非旋treap·毒瘤题]

    P2042 [NOI2005]维护数列 数列区间和,最大子列和(必须不为空),支持翻转.修改值.插入删除. 练码力的题,很毒瘤.个人因为太菜了,对splay极其生疏,犯了大量错误,在此记录,望以后一定 ...

  6. Luogu P2042 [NOI2005]维护数列(平衡树)

    P2042 [NOI2005]维护数列 题意 题目描述 请写一个程序,要求维护一个数列,支持以下\(6\)种操作:(请注意,格式栏中的下划线'_'表示实际输入文件中的空格) 输入输出格式 输入格式: ...

  7. [NOI2005]维护数列(区间splay)

    [NOI2005]维护数列(luogu) 打这玩意儿真是要了我的老命 Description 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文 ...

  8. [转载]无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )

    转自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182631.html 1500: [NOI2005]维修数列 Time Limit: 10 Sec  Mem ...

  9. [您有新的未分配科技点] 无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Description Input 输入的第1 行包含两个数N 和M(M ≤20 ...

  10. 【bzoj1500】 noi2005—维护数列

    http://www.lydsy.com/JudgeOnline/problem.php?id=1500 (题目链接) 题意 要求维护数列,操作有区间删除,区间插入,区间反转,区间修改,区间求和,求最 ...

随机推荐

  1. Failed to create a 'System.Type' from the text ' ' in wpf(无法从文本创建类型)

    问题描述:WPF is unable to create a type for data templateWPF使用mvvm模式无法加载DataTemplate模板定义的资源,提示无法从文本创建类型错 ...

  2. NFS文件共享系统

    1.NFS介绍 NFS是Network File System的缩写,主要功能是通过网络让不同的机器系统之间可以彼此共享文件或目录.NFS服务器可以允许NFS客户端将远端NFS服务端的共享目录挂载到本 ...

  3. Object-C内存管理

    Object-C的内存管理是基于引用计数的.你要做的事情只是关注你的引用,而释放内存的工作实际上由运行环境完成. 在最简单的情形中,你分配(alloc)的对象,或只是保留(retain)在一些地方的对 ...

  4. Implicit conversion from enumeration type 'enum CGImageAlphaInfo' to different enumeration type 'CGB

    Implicit conversion from enumeration type 'enum CGImageAlphaInfo' to different enumeration type 'CGB ...

  5. Java 编译解释

    JDK提供的主要开发工具有:编译程序,解释执行程序.调试程序.Applet执行程序.文档管理程序.包管理程序等. 1.编译程序:javac.exe,对应的javac命令将Java源程序转换为字节码. ...

  6. 多语言文本资源的访问(Windows:ini)

    目标 本文要讨论对于开发多语言界面程序所需要解决的一个问题,即文本资源组织及访问的方法. 本文主要以Windows平台下讨论具现并提供处理代码. Windows方案 Windows下界面开发,除Dir ...

  7. linux中python环境搭建及升级后yum不可用解决方案

    1.1 LinuxCentOS 为例.1.1.1 升级 Python(1) 下载 Python 版本$ wget https://www.python.org/ftp/python/2.7.11/Py ...

  8. TDirectory.Delete 创建删除目录简单示例

    使用函数: 1.System.IOUtils.TDirectory.CreateDirectory//创建目录 2.System.IOUtils.TDirectory.Exists        // ...

  9. ubuntu下的supervisor启动express失败问题

    ubuntu下apt-get install nodejs后的启动命令是nodejs,而不同于windows下的node 所以我在supervisor启动express的时候出现了问题 提示如下: / ...

  10. 简单vim配置

    对于一个学习C++的人来说,我常用VS写代码,而Linux环境也是很重要的.最近学习了Linux的一些基本内容后,开始了vim编辑器的使用.然而它刚开始的界面着实令人很不习惯~~~于是我尝试着把它装饰 ...