题意:

输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

思路:集大成的splay模板,写完就去学LCT了

注意可能会爆INT64,改了好久,我也不知道c++为什么不开long long能过

这题卡内存,需要数组垃圾回收

 const oo=;

 var t:array[..,..]of longint;
sum,lx,rx,mx:array[..]of int64;
tag,rev,a,b,fa,id,d,size:array[..]of longint;
q:array[..]of longint;
n,m,i,j,k,x,f,root,cnt,head,tail,s:longint;
ch:ansistring; function max(x,y:int64):int64;
begin
if x>y then exit(x);
exit(y);
end; procedure swap(var x,y:int64);
var t:int64;
begin
t:=x; x:=y; y:=t;
end; procedure pushup(x:longint);
var l,r:longint;
begin
l:=t[x,]; r:=t[x,];
sum[x]:=sum[l]+sum[r]+b[x];
size[x]:=size[l]+size[r]+;
mx[x]:=max(mx[l],mx[r]);
mx[x]:=max(mx[x],rx[l]+lx[r]+b[x]);
lx[x]:=max(lx[l],sum[l]+b[x]+lx[r]);
rx[x]:=max(rx[r],sum[r]+b[x]+rx[l]);
end; procedure pushdown(x:longint);
var l,r,tmp:longint;
begin
l:=t[x,]; r:=t[x,];
if tag[x]> then
begin
rev[x]:=; tag[x]:=;
if l> then
begin
tag[l]:=; b[l]:=b[x]; sum[l]:=b[x]*size[l];
end;
if r> then
begin
tag[r]:=; b[r]:=b[x]; sum[r]:=b[x]*size[r];
end;
if b[x]>= then
begin
if l> then
begin
lx[l]:=sum[l]; rx[l]:=sum[l]; mx[l]:=sum[l];
end;
if r> then
begin
lx[r]:=sum[r]; rx[r]:=sum[r]; mx[r]:=sum[r];
end;
end
else
begin
if l> then
begin
lx[l]:=; rx[l]:=; mx[l]:=b[x];
end;
if r> then
begin
lx[r]:=; rx[r]:=; mx[r]:=b[x];
end;
end;
end;
if rev[x]> then
begin
rev[x]:=rev[x] xor ; rev[l]:=rev[l] xor ; rev[r]:=rev[r] xor ;
//tmp:=lx[l]; lx[l]:=rx[l]; rx[l]:=tmp;
//tmp:=lx[r]; lx[r]:=rx[r]; rx[r]:=tmp;
tmp:=t[l,]; t[l,]:=t[l,]; t[l,]:=tmp;
tmp:=t[r,]; t[r,]:=t[r,]; t[r,]:=tmp; swap(lx[l],rx[l]); swap(lx[r],rx[r]);
// swap(t[l,],t[l,]); swap(t[r,],t[r,]);
end;
end; procedure rotate(x:longint;var k:longint);
var y,z,l,r:longint;
begin
y:=fa[x]; z:=fa[y];
if t[y,]=x then l:=
else l:=;
r:=l xor ;
if y<>k then
begin
if t[z,]=y then t[z,]:=x
else t[z,]:=x;
end
else k:=x;
fa[t[x,r]]:=y; fa[x]:=z; fa[y]:=x;
t[y,l]:=t[x,r]; t[x,r]:=y;
pushup(y);
pushup(x);
end; procedure splay(x:longint;var k:longint);
var y,z:longint;
begin
while x<>k do
begin
y:=fa[x]; z:=fa[y];
if y<>k then
begin
if (t[y,]=x)xor(t[z,]=y) then rotate(x,k)
else rotate(y,k);
end
else k:=x;
rotate(x,k);
end;
end; procedure build(l,r,x:longint);
var mid,now,last:longint;
begin
if l>r then exit;
mid:=(l+r)>>; now:=id[mid]; last:=id[x];
if l=r then
begin
sum[now]:=a[l]; size[now]:=;
tag[now]:=; rev[now]:=;
if a[l]>= then
begin
lx[now]:=a[l]; rx[now]:=a[l]; mx[now]:=a[l];
end
else
begin
lx[now]:=; rx[now]:=; mx[now]:=a[l];
end;
end
else
begin
build(l,mid-,mid);
build(mid+,r,mid);
end;
b[now]:=a[mid]; fa[now]:=last;
pushup(now);
if mid>=x then t[last,]:=now
else t[last,]:=now;
end; function find(x,k:longint):longint;
var l,r:longint;
begin
pushdown(x);
l:=t[x,]; r:=t[x,];
if size[l]+=k then exit(x);
if size[l]+>k then exit(find(l,k))
else exit(find(r,k-size[l]-));
end; procedure clear(x:longint);
var l,r:longint;
begin
if x= then exit;
l:=t[x,]; r:=t[x,];
clear(l); clear(r);
inc(tail); q[tail mod ]:=x; //队列,记录以前用过但现在已经被删除,可以使用的编号 fa[x]:=; t[x,]:=; t[x,]:=;
tag[x]:=; rev[x]:=;
end; function split(k,tot:longint):longint;
var x,y:longint;
begin
x:=find(root,k); y:=find(root,k+tot+);
splay(x,root); splay(y,t[x,]);
exit(t[y,]);
end; procedure query(k,tot:longint);
var x:longint;
begin
x:=split(k,tot);
writeln(sum[x]);
end; procedure del(k,tot:longint);
var x,y:longint;
begin
x:=split(k,tot); y:=fa[x];
clear(x); t[y,]:=;
pushup(y);
pushup(fa[y]);
end; procedure change(k,tot,v:longint);
var x,y:longint;
begin
x:=split(k,tot); y:=fa[x];
b[x]:=v; tag[x]:=; sum[x]:=size[x]*v;
if v>= then
begin
lx[x]:=sum[x]; rx[x]:=sum[x]; mx[x]:=sum[x];
end
else
begin
lx[x]:=; rx[x]:=; mx[x]:=v;
end;
pushup(y);
pushup(fa[y]);
end; procedure rever(k,tot:longint);
var x,y,tmp:longint;
begin
x:=split(k,tot); y:=fa[x];
if tag[x]= then
begin
rev[x]:=rev[x] xor ;
tmp:=t[x,]; t[x,]:=t[x,]; t[x,]:=tmp;
// swap(t[x,],t[x,]);
swap(lx[x],rx[x]);
pushup(y);
pushup(fa[y]);
end;
end; procedure ins(k,tot:longint);
var x,y,z,i:longint;
begin
for i:= to tot do
if tail>=head then begin id[i]:=q[head mod ]; inc(head); end //垃圾回收
else begin inc(cnt); id[i]:=cnt; end;
build(,tot,); z:=id[(tot+)>>];
x:=find(root,k+); y:=find(root,k+);
splay(x,root); splay(y,t[x,]);
fa[z]:=y; t[y,]:=z;
pushup(y);
pushup(x);
end; begin readln(n,m);
head:=; tail:=;
mx[]:=-oo; a[]:=-oo; a[n+]:=-oo;
for i:= to n+ do read(a[i]);
readln;
for i:= to n+ do id[i]:=i;
build(,n+,);
root:=(n+)>>; cnt:=n+;
for i:= to m do
begin
for j:= to do d[j]:=;
readln(ch); s:=;
k:=length(ch); f:=; x:=;
for j:= to k do
begin
if (ch[j]>='A')and(ch[j]<='Z')or((ch[j]='-')and(s=)) then continue;
if ch[j]=' ' then
begin
if s> then d[s]:=f*x;
inc(s);
x:=; f:=;
continue;
end;
if ch[j]='-' then
begin
f:=-; continue;
end;
x:=x*+ord(ch[j])-ord('');
end;
d[s]:=f*x;
ch:=copy(ch,,);
if ch='INS' then
begin
for j:= to d[] do a[j]:=d[j+];
ins(d[],d[]);
end;
if ch='DEL' then del(d[],d[]);
if ch='MAK' then change(d[],d[],d[]);
if ch='REV' then rever(d[],d[]);
if ch='GET' then
if d[]= then writeln()
else query(d[],d[]);
if ch='MAX' then writeln(mx[root]);
end; end.

UPD(2018.9.17):C++

 #include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef vector<int> VI;
#define fi first
#define se second
#define MP make_pair
#define N 1100000
#define MOD 1000000007
#define eps 1e-8
#define pi acos(-1)
#define oo 1e9 int a[N],id[N],fa[N],t[N][],sum[N],size[N],v[N],mx[N],lx[N],rx[N],
tag[N],rev[N],n,m,root,cnt;
queue<int> q; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} void pushup(int x)
{
int l=t[x][];
int r=t[x][];
sum[x]=sum[l]+sum[r]+v[x];
size[x]=size[l]+size[r]+;
mx[x]=max(mx[l],mx[r]);
mx[x]=max(mx[x],rx[l]+v[x]+lx[r]);
lx[x]=max(lx[l],sum[l]+v[x]+lx[r]);
rx[x]=max(rx[r],sum[r]+v[x]+rx[l]);
} void pushdown(int x)
{
int l=t[x][];
int r=t[x][];
if(tag[x])
{
rev[x]=tag[x]=;
if(l){tag[l]=; v[l]=v[x]; sum[l]=v[x]*size[l];}
if(r){tag[r]=; v[r]=v[x]; sum[r]=v[x]*size[r];}
if(v[x]>=)
{
if(l) lx[l]=rx[l]=mx[l]=sum[l];
if(r) lx[r]=rx[r]=mx[r]=sum[r];
}
else
{
if(l){lx[l]=rx[l]=; mx[l]=v[x];}
if(r){lx[r]=rx[r]=; mx[r]=v[x];}
}
}
if(rev[x])
{
rev[x]^=; rev[l]^=; rev[r]^=;
swap(lx[l],rx[l]);
swap(lx[r],rx[r]);
swap(t[l][],t[l][]);
swap(t[r][],t[r][]);
}
} void rotate(int x,int &k)
{
int y=fa[x];
int z=fa[y];
int l;
if(t[y][]==x) l=;
else l=;
int r=l^;
if(y!=k)
{
if(t[z][]==y) t[z][]=x;
else t[z][]=x;
}
else k=x;
fa[t[x][r]]=y; fa[x]=z; fa[y]=x;
t[y][l]=t[x][r]; t[x][r]=y;
pushup(y);
pushup(x);
} void splay(int x,int &k)
{
while(x!=k)
{
int y=fa[x];
int z=fa[y];
if(y!=k)
{
if(t[y][]==x^t[z][]==y) rotate(x,k);
else rotate(y,k);
}
else k=x;
rotate(x,k);
}
} int find(int x,int rank)
{
pushdown(x);
int l=t[x][];
int r=t[x][];
if(size[l]+==rank) return x;
if(size[l]>=rank) return find(l,rank);
return find(r,rank-size[l]-);
} void rec(int x)
{
if(!x) return;
int l=t[x][];
int r=t[x][];
rec(l);
rec(r);
q.push(x);
fa[x]=t[x][]=t[x][]=tag[x]=rev[x]=;
} int split(int k,int tot)
{
int x=find(root,k);
int y=find(root,k+tot+);
splay(x,root);
splay(y,t[x][]);
return t[y][];
} void query(int k,int tot)
{
int x=split(k,tot);
printf("%d\n",sum[x]);
} void update(int k,int tot,int val)
{
int x=split(k,tot);
int y=fa[x];
v[x]=val; tag[x]=; sum[x]=size[x]*val;
if(val>=) lx[x]=rx[x]=mx[x]=sum[x];
else{lx[x]=rx[x]=; mx[x]=val;}
pushup(y);
pushup(fa[y]);
} void rever(int k,int tot)
{
int x=split(k,tot);
int y=fa[x];
if(!tag[x])
{
rev[x]^=;
swap(t[x][],t[x][]);
swap(lx[x],rx[x]);
pushup(y);
pushup(fa[y]);
}
} void Delete(int k,int tot)
{
int x=split(k,tot);
int y=fa[x];
rec(x);
t[y][]=;
pushup(y);
pushup(fa[y]);
} void build(int l,int r,int p)
{
if(l>r) return;
int mid=(l+r)>>;
int now=id[mid];
int last=id[p];
if(l==r)
{
sum[now]=a[l];
size[now]=;
tag[now]=rev[now]=;
if(a[l]>=) lx[now]=rx[now]=mx[now]=a[l];
else{lx[now]=rx[now]=; mx[now]=a[l];}
}
else
{
build(l,mid-,mid);
build(mid+,r,mid);
}
v[now]=a[mid];
fa[now]=last;
pushup(now);
t[last][mid>=p]=now;
} void Insert(int k,int tot)
{
for(int i=;i<=tot;i++) a[i]=read();
for(int i=;i<=tot;i++)
if(!q.empty()){id[i]=q.front(); q.pop();}
else id[i]=++cnt;
build(,tot,);
int z=id[(tot+)>>];
int x=find(root,k+);
int y=find(root,k+);
splay(x,root);
splay(y,t[x][]);
fa[z]=y;
t[y][]=z;
pushup(y);
pushup(x);
} int main()
{
//freopen("bzoj1500.in","r",stdin);
//freopen("bzoj1500.out","w",stdout);
n=read();
m=read();
mx[]=a[]=a[n+]=-oo;
for(int i=;i<=n+;i++) a[i]=read();
for(int i=;i<=n+;i++) id[i]=i;
build(,n+,);
root=(n+)>>;
cnt=n+;
int x,y,z;
char ch[];
while(m--)
{
scanf("%s",ch);
if(ch[]!='M'||ch[]!='X') scanf("%d%d",&x,&y);
if(ch[]=='I') Insert(x,y);
if(ch[]=='D') Delete(x,y);
if(ch[]=='M')
{
if(ch[]=='X') printf("%d\n",mx[root]);
else
{
z=read();
update(x,y,z);
}
}
if(ch[]=='R') rever(x,y);
if(ch[]=='G') query(x,y);
}
return ;
}

【BZOJ1500】维修数列(splay)的更多相关文章

  1. 【BZOJ1500】[NOI2005]维修数列 Splay

    [BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行 ...

  2. 【BZOJ-1500】维修数列 Splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 11047  Solved: 3460[Submit][Statu ...

  3. bzoj 1500: [NOI2005]维修数列 splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 6556  Solved: 1963[Submit][Status ...

  4. [BZOJ 1500]维修数列 [Splay Tree从进阶到住院]

    历尽艰辛终于A掉了这题QwQ 贴COGS评论区几句话=.= 策爷:"splay/块状链表的自虐题.".深刻理解到如果没有M倾向就不要去写这题了.. -Chenyao2333 记得b ...

  5. BZOJ 1500: [NOI2005]维修数列 (splay tree)

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 4229  Solved: 1283[Submit][Status ...

  6. [bzoj1269]文本编辑器editor [bzoj1500]维修数列

    1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2540 Solved: 923 [Submit ...

  7. BZOJ1500: [NOI2005]维修数列[splay ***]

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 12278  Solved: 3880[Submit][Statu ...

  8. [bzoj1500][NOI2005]维修数列——splay

    题目 题解 这道题可以说是数列问题的大BOSS,也算是这一周来学习splay等数据结构的一个总结. 我们一个一个地看这些操作. 对于操作1,我们首先建一棵子树,直接接上原树即可. 对于操作2,我们找到 ...

  9. BZOJ1500: [NOI2005]维修数列 [splay序列操作]【学习笔记】

    以前写过这道题了,但我把以前的内容删掉了,因为现在感觉没法看 重写! 题意: 维护一个数列,支持插入一段数,删除一段数,修改一段数,翻转一段数,查询区间和,区间最大子序列 splay序列操作裸题 需要 ...

  10. [bzoj1500][NOI2005 维修数列] (splay区间操作)

    Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目. 第2行包含N个数字,描述初始时的数列. 以下M行,每 ...

随机推荐

  1. ABC3D创客项目:小风扇

    风扇是我们纳凉的好帮手,然而大多的风扇都体积庞大不易携带.利用电池进行供电能让风扇变得更加便捷,下面我们利用电池供电的原理制作出一个风扇. 工作原理: 这个OK风扇的主要能源来自于后面的7号电池,风扇 ...

  2. 几个不错的APP网站。

    http://www.yunshipei.com/yunshipei.html http://www.appcan.cn/

  3. HDU 6052 To my boyfriend(容斥+单调栈)

    题意:对于一个n*m的方格,每个格子中都包含一种颜色,求出任意一个矩形包含不同颜色的期望. 思路: 啊啊啊啊啊,补了两天,总算A了这道题了,简直石乐志,前面的容斥还比较好写,后面的那个>13那个 ...

  4. JS中的事件、事件冒泡和事件捕获、事件委托

    https://www.cnblogs.com/diver-blogs/p/5649270.html https://www.cnblogs.com/Chen-XiaoJun/p/6210987.ht ...

  5. ios retain copy 以及copy协议

    阅读本文之前首先了解Copy与Retain的区别: Copy是创建一个新对象,Retain是创建一个指针,引用对象计数加1. Copy属性表示两个对象内容相同,新的对象retain为1 ,与旧有对象的 ...

  6. Mac 电源管理

    在安装BatteryManager后,可以删除NullPowerMananger,AppleIntelPowerMananger, AppleIntelPowerClientMananger三个kex ...

  7. JS设置组合快捷键

    为提升用户体验,想要在web页面中通过组合快捷键调出用户帮助页面,具体实现思路是监听keyup事件,在相应的处理函数中进行逻辑编写,代码如下 $(document).keyup(function (e ...

  8. MySQL常用表结构查询语句

    在我们使用数据库进行查询或者建表时,经常需要查看表结构,下面以employees数据库中的departments表为例进行表结构查询: departments表:(2列9行) +---------+- ...

  9. python常用内置函数用法精要

    用一个表格大致总结一下所有的内置函数用法,如下: 函数 功能简要说明 abs(x) 返回数字x的绝对值或复数x的模 all(iterable) 如果对于可迭代对象中所有元素x都等价于True,则返回T ...

  10. (三)Python3 循环语句——while

    while语句的一般形式: while 判断条件: 语句 同样需要注意冒号和缩进.另外,在 Python 中没有 do..while 循环. 以下实例使用了 while 来计算 1 到 100 的总和 ...