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 ...
随机推荐
- CentOS 6使用iostat
iostat/mpstat/sar等命令属于sysstat程序包,所以使用yum安装sysstat即可. yum install sysstat
- oracle 11g 安装及网络配置
非原创,纯属笔记 安装:基本按照默认下一步安装的 1)可执行安装文件[ setup.exe ]双击安装 2):配置安全更新,取消下面的“我希望通过My Oracle Support接受安全更新(W)” ...
- Html+Css+Js_之table每隔3行显示不同的两种颜色
<html> <head> <script type="text/javascript"> /** 最近因项目的需求,有这样的一个问题: 一个t ...
- Socket服务器整体架构概述
转载:http://www.cnblogs.com/tianzhiliang/archive/2010/10/28/1863684.html Socket服务器主要用于提供高效.稳定的数据处理.消息转 ...
- 在fragment中调用SharedPreferences
[o] Activity中调用SharedPreferences的方式: String prefsName = "mysetting"; SharedPreferences pre ...
- c语言学习之基础知识点介绍(四):算术运算符和逗号表达式
本节主要介绍c语言中运算符. 运算符主要分为四类: 1.算术运算符 加(+),减(-),乘(*),除(/),取余(%,两数相除,得到余数) 2.关系运算符 3.逻辑运算符 4.换位运算符 下面将依次介 ...
- Java23种设计模式之单例模式
一.单例模式简介 单例模式是Java设计模式中常见的一种模式.主要分为懒汉式单例.饿汉式单例.登记式单例: 单例模式的特点: 1.单例类只能有一个实例: 2.单例类必须自己创建自己的唯一的实例: ...
- 一行代码实现headView弹簧拉伸效果
前言 很多app的个人中心上部的headView都实现了弹簧拉伸的效果,即tableView的top并不随着下拉而滑动,而是紧紧的停在屏幕的最上方. 我们今天就分析一下这个效果的实现方式. 分析 关键 ...
- CSS 列表
CSS列表属性作用如下: 设置不同的列表项标记为有序列表 设置不同的列表项标记为无序列表 设置列表项标记为图像 列表 在HTML中,有两种类型的列表: 无序列表 - 列表项标记用特殊图形(如小黑点.小 ...
- 策略模式(Strategy)
行为型模式:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式 策略模式(Strategy) 策略模式定义了一系列算法,并将 ...