poj3580
区间操作的究极题,我们一个个来分析
其实只有insert,delete,revolve三种没讲过
insert 先把x旋到根,一开始我比较SB的,准备把新节点插入到右子树的最左节点,这显然很烦
好的方法是,直接在根和右孩子之间插入即可,相当于right[new]=right[root] right[root]=new
然后维护一下new和root即可即可
delete 我一开始使用的是杨思雨大神splay论文中的方法,但是好像很烦
后来发现,一个比较简洁的做法,先把x的后继旋到根,然后把x旋到根的儿子的位置上(显然是左孩子)
显然x是不含有右子树的,所以,直接删去x即可(就是x的左子树直接与根相连
revolve 这是这道题最难的一个操作了,感觉自己写的也不是很好,还是讲讲方法吧
首先这个操作的本质是[l,k][k+1,r]这两个区间交换位置
考虑到假如在k和k+1中间有一个中间点,那么我只要把中间点旋到区间的根上然后直接交换左右子树即可
但是是不存在的,所以我们考虑先把k作为这个中间点,交换完左右子树后再把k插入到区间最后
也就是先把k旋到区间根上,然后交换左右子树,然后把k节点删去,再把他插入区间末尾
如果l=k,就不需要删去插入这一步了,感觉写得挺麻烦的
const inf=; var son:array[..,..] of longint;
count,fa,a,lazy,mina:array[..] of longint;
v:array[..] of boolean;
n,m,i,x,y,z,p,root:longint;
s:string;
ch:char; function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; procedure add(x,y:longint);
begin
mina[x]:=mina[x]+y;
a[x]:=a[x]+y;
lazy[x]:=lazy[x]+y;
end; procedure change(x:longint);
begin
swap(son[x,],son[x,]);
v[x]:=not v[x];
end; procedure update(x:longint);
begin
count[x]:=count[son[x,]]+count[son[x,]]+;
mina[x]:=min(a[x],min(mina[son[x,]],mina[son[x,]]));
end; procedure push(x:longint);
var l,r:longint;
begin
l:=son[x,];
r:=son[x,];
if lazy[x]<> then
begin
if l<>- then add(l,lazy[x]);
if r<>- then add(r,lazy[x]);
lazy[x]:=;
end;
if v[x] then
begin
if l<>- then change(l);
if r<>- then change(r);
v[x]:=false;
end;
end; procedure rotate(x,w:longint);
var y:longint;
begin
push(x);
y:=fa[x];
if fa[y]<>- then
begin
if son[fa[y],]=y then son[fa[y],]:=x
else son[fa[y],]:=x;
end
else root:=x;
fa[x]:=fa[y];
son[y,-w]:=son[x,w];
if son[x,w]<>- then fa[son[x,w]]:=y;
son[x,w]:=y;
fa[y]:=x;
update(y);
update(x);
end; procedure splay(x,f:longint);
var y:longint;
begin
while fa[x]<>f do
begin
y:=fa[x];
if fa[y]=f then
begin
if son[y,]=x then rotate(x,)
else rotate(x,);
end
else begin
if son[fa[y],]=y then
begin
if son[y,]=x then rotate(y,) else rotate(x,);
rotate(x,);
end
else begin
if son[y,]=x then rotate(x,) else rotate(y,);
rotate(x,);
end;
end;
end;
end; function find(k:longint):longint;
var p:longint;
begin
p:=root;
while true do
begin
push(p);
if count[son[p,]]+=k then exit(p);
if count[son[p,]]+>k then p:=son[p,]
else begin
k:=k-count[son[p,]]-;
p:=son[p,];
end;
end;
end; procedure getrange; //提取区间
begin
x:=find(x);
y:=find(y+);
splay(x,-);
splay(y,x);
end; procedure insert(x,p:longint); // p是新插入节点
begin
splay(x,-);
son[p,]:=son[x,];
fa[son[x,]]:=p;
son[x,]:=p;
fa[p]:=x;
update(p);
update(x);
end; procedure delete(x,p:longint); //p是x的后继节点
begin
splay(p,-);
splay(x,p);
if son[x,]<>- then fa[son[x,]]:=p;
son[p,]:=son[x,];
son[x,]:=-;
son[x,]:=-;
fa[x]:=-;
update(p);
end; function build(l,r:longint):longint;
var m:longint;
begin
m:=(l+r) shr ;
build:=m;
if m->=l then
begin
son[m,]:=build(l,m-);
fa[son[m,]]:=m;
end;
if m+<=r then
begin
son[m,]:=build(m+,r);
fa[son[m,]]:=m;
end;
update(m);
end; procedure revolve;
var l,r,p,last:longint;
begin
last:=find(y-z+); // 交换[x,y-z][y-z+,y];
if y-z=x then
begin
getrange;
splay(last,y);
swap(son[last,],son[last,]);
end
else begin
l:=x;
r:=y;
getrange;
splay(last,y);
swap(son[last,],son[last,]);
//交换完后,中间点对应区间上的点也不同了
p:=find(l+z+); //注意这里两处找位置对应树上的点,交换删除后,同一位置对应树上的点会不不同
delete(last,p);
p:=find(r);
insert(p,last);
end;
end; begin
readln(n);
fillchar(son,sizeof(son),);
fillchar(fa,sizeof(fa),);
for i:= to n do
readln(a[i]);
for i:=- to n+ do
mina[i]:=inf;
count[-]:=;
a[-]:=inf;
a[]:=inf;
a[n+]:=inf;
root:=build(,n+);
inc(n);
readln(m);
for i:= to m do
begin
read(ch);
s:='';
while ch<>' ' do
begin
s:=s+ch;
read(ch);
end;
if s='ADD' then
begin
readln(x,y,z);
getrange;
add(son[y,],z);
end
else if s='REVERSE' then
begin
readln(x,y);
getrange;
change(son[y,]);
end
else if s='REVOLVE' then
begin
readln(x,y,z);
z:=z mod (y-x+); //注意
if z<> then revolve;
end
else if s='INSERT' then
begin
readln(x,y);
x:=find(x+);
inc(n); mina[n]:=y; a[n]:=y; count[n]:=;
insert(x,n);
end
else if s='DELETE' then
begin
readln(x);
p:=find(x+);
x:=find(x+);
delete(x,p);
end
else begin
readln(x,y);
getrange;
writeln(mina[son[y,]]);
end;
end;
end.
poj3580的更多相关文章
- poj3580 splay树 REVOVLE循环
SuperMemo Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 12795 Accepted: 3989 Case T ...
- poj3580 伸展树(区间翻转 区间搬移 删除结点 加入结点 成段更新)
好题.我做了很久,学了大牛们的区间搬移.主要的代码都有注释. #include<cstdio> #include<cstring> #include<iostream&g ...
- 【POJ3580】【splay版】SuperMemo
Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant i ...
- 【POJ3580】【块状链表】SuperMemo
Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant i ...
- POJ3580 SuperMemo splay伸展树,区间操作
题意:实现一种数据结构,支持对一个数列的 6 种操作:第 x 个数到第 y 个数之间的数每个加 D:第 x 个数到第 y 个数之间全部数翻转:第 x 个数到第 y 个数之间的数,向后循环流动 c 次, ...
- POJ3580 SuperMemo
Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to pl ...
- Poj3580 Super Memo(FHQ-Treap)
题面 题解 对于操作$1$,我们可以对于每个节点打一个$add$标记,下放就行了 对于操作2,可以参考这篇题解的上一篇,不赘述 对于操作4,可以将区间裂成两部分,然后再插入合并 对于操作5,可以将区间 ...
- poj3580 序列之王 fhqtreap
fhqtreap的写法 操作其实都差不多哇 #include<cstdio> #include<cstring> #include<algorithm> using ...
- POJ3580:SuperMemo
浅谈\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html 浅谈\(fhq\)_\(treap\):https://www.cnblogs.com ...
随机推荐
- Genymotion无法启动Virtual Box
Genymotion是非常快速的Android模拟器.这两天搞了一下Android Studio,想用Genymotion跑起一下,但死活都启动不了.很奇怪,明明几个月前还顺利启动的. Genymot ...
- SQL Server中建立外键的方法
在SQL中建立外键约束,可以级联查询表中的数据,在C#代码生成器中,也能根据外键关系生成相应的外键表数据模型.外键也可防止删除有外键关系的记录,一定程度上保护了数据的安全性. 步骤: 1.要建立外键关 ...
- javascript的面向对象编程
面象对象编程技术的核心理念:封装.继承.多态:在一些主流的高级编程语言中,比如:C#,VB.NET,JAVA,PHP等都是很容易实现的,而如果要在javascript中实现面象对象编程,可就不那么直接 ...
- .NET设计模式(4):建造者模式(Builder Pattern)
):建造者模式(Builder Pattern) .建造者模式的使用使得产品的内部表象可以独立的变化.使用建造者模式可以使客户端不必知道产品内部组成的细节. 2.每一个Builder都相对独立, ...
- sqlserver2005唯一性约束
[转载]http://blog.163.com/rihui_7/blog/static/21228514320136193392749/ 1.设置字段为主键就是一种唯一性约束的方法,如 int p ...
- WEB系统开发方向
1. UI框架:要可以结合jquery+自定义服务器控件开发一套UI框架: 2.WEB报表设计器:用js开发一套可以自定义报表设计器: 3.WEB自定义表单+工作流设计器: 4.WEB打印组件: 5. ...
- jsoup:解析HTML用法小结
1.解析方式 (1)从字符串解析 ? 1 2 3 String html = "<html><head><title>First parse</ti ...
- OC - 14.NSOperation与NSOperationQueue
简介 通过NSOperation与NSOperationQueue的组合也能实现多线程 通常将任务封装成NSOperation对象,并将对象添加到NSOperationQueue中实现 NSOpera ...
- html-----001
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- C蛮的全栈之路-node篇(二) 实战一:自动发博客
目录 C蛮的全栈之路-序章 技术栈选择与全栈工程师C蛮的全栈之路-node篇(一) 环境布置C蛮的全栈之路-node篇(二) 实战一:自动发博客 ---------------- 我是分割线 ---- ...