【BZOJ1500】维修数列(splay)
题意:
输入的第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)的更多相关文章
- 【BZOJ1500】[NOI2005]维修数列 Splay
[BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行 ...
- 【BZOJ-1500】维修数列 Splay
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 11047 Solved: 3460[Submit][Statu ...
- bzoj 1500: [NOI2005]维修数列 splay
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 6556 Solved: 1963[Submit][Status ...
- [BZOJ 1500]维修数列 [Splay Tree从进阶到住院]
历尽艰辛终于A掉了这题QwQ 贴COGS评论区几句话=.= 策爷:"splay/块状链表的自虐题.".深刻理解到如果没有M倾向就不要去写这题了.. -Chenyao2333 记得b ...
- BZOJ 1500: [NOI2005]维修数列 (splay tree)
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 4229 Solved: 1283[Submit][Status ...
- [bzoj1269]文本编辑器editor [bzoj1500]维修数列
1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2540 Solved: 923 [Submit ...
- BZOJ1500: [NOI2005]维修数列[splay ***]
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 12278 Solved: 3880[Submit][Statu ...
- [bzoj1500][NOI2005]维修数列——splay
题目 题解 这道题可以说是数列问题的大BOSS,也算是这一周来学习splay等数据结构的一个总结. 我们一个一个地看这些操作. 对于操作1,我们首先建一棵子树,直接接上原树即可. 对于操作2,我们找到 ...
- BZOJ1500: [NOI2005]维修数列 [splay序列操作]【学习笔记】
以前写过这道题了,但我把以前的内容删掉了,因为现在感觉没法看 重写! 题意: 维护一个数列,支持插入一段数,删除一段数,修改一段数,翻转一段数,查询区间和,区间最大子序列 splay序列操作裸题 需要 ...
- [bzoj1500][NOI2005 维修数列] (splay区间操作)
Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目. 第2行包含N个数字,描述初始时的数列. 以下M行,每 ...
随机推荐
- The - Modcrab——使用贪心策略
一.题目信息 The - Modcrab 简单翻译一下:Vova有生命值h1,每次攻击值为a1,每瓶药水恢复生命值c1;Modcrab有生命值h2,每次攻击值为a2.在每个关卡开始,Vova有两种选择 ...
- 小白安装python软件
首先下载:anaconda3.x 下载方式:百度搜索 清华镜像anaconda https://mirrors.tuna.tsinghua.edu.cn/help/anacond ...
- Vue的elementUI实现自定义主题
使用vue开发项目,用到elementUI,根据官网的写法,我们可以自定义主题来适应我们的项目要求,下面来介绍一下两种方法实现的具体步骤,(可以参考官方文档自定义主题官方文档),先说项目中没有使用sc ...
- 新版raspbian系统的固定IP配置和启用root账户的ssh登录功能的方法
1. 2016新版raspbian系统的固定IP配置: 自2016年2月份新版raspbian系统发布以后,树莓派的固定IP配置方法就与之前不一样了. 之前在raspbian系统中编辑/etc/net ...
- 服务器配置iis,php网站
1.在iis中选择物理路径.配置域名 2.添加php默认文档 3.修改处理程序映射 4.设置模块映射信息
- Struts2 执行流程
struts2执行原理(执行流程) 一个请求在Struts2框架中的处理大概分为以下几个步骤: 1 客户端发送请求:(HttpServletRequest)2 这个请求经过一系列的过滤器(Filter ...
- HTML5拖放(drag和drog)作品
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- vue父组件获取子组件页面的数组 以城市三级联动为例
父组件调用子组件 <Cselect ref="registerAddress"></Cselect> import Cselect from '../../ ...
- python mysql备份脚本
#!/usr/bin/env python # encoding: utf-8 #@author: 东哥加油! #@file: pyinnobackup.py #@time: 2018/12/11 1 ...
- PHP中文件锁与进程锁的使用区别
php中文网的一篇文章,收为己用了.源地址: http://www.php.cn/php-weizijiaocheng-376853.html 本篇文章主要介绍了PHP 文件锁与进程锁的使用示例,小编 ...