区间操作的究极题,我们一个个来分析
其实只有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的更多相关文章

  1. poj3580 splay树 REVOVLE循环

    SuperMemo Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 12795   Accepted: 3989 Case T ...

  2. poj3580 伸展树(区间翻转 区间搬移 删除结点 加入结点 成段更新)

    好题.我做了很久,学了大牛们的区间搬移.主要的代码都有注释. #include<cstdio> #include<cstring> #include<iostream&g ...

  3. 【POJ3580】【splay版】SuperMemo

    Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant i ...

  4. 【POJ3580】【块状链表】SuperMemo

    Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant i ...

  5. POJ3580 SuperMemo splay伸展树,区间操作

    题意:实现一种数据结构,支持对一个数列的 6 种操作:第 x 个数到第 y 个数之间的数每个加 D:第 x 个数到第 y 个数之间全部数翻转:第 x 个数到第 y 个数之间的数,向后循环流动 c 次, ...

  6. POJ3580 SuperMemo

    Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to pl ...

  7. Poj3580 Super Memo(FHQ-Treap)

    题面 题解 对于操作$1$,我们可以对于每个节点打一个$add$标记,下放就行了 对于操作2,可以参考这篇题解的上一篇,不赘述 对于操作4,可以将区间裂成两部分,然后再插入合并 对于操作5,可以将区间 ...

  8. poj3580 序列之王 fhqtreap

    fhqtreap的写法 操作其实都差不多哇 #include<cstdio> #include<cstring> #include<algorithm> using ...

  9. POJ3580:SuperMemo

    浅谈\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html 浅谈\(fhq\)_\(treap\):https://www.cnblogs.com ...

随机推荐

  1. GitHub详细教程

    GitHub详细教程 Table of Contents 1 Git详细教程 1.1 Git简介 1.1.1 Git是何方神圣? 1.1.2 重要的术语 1.1.3 索引 1.2 Git安装 1.3 ...

  2. HTML5本地化应用开发-HTML5 Web存储详解

    文章不是简单的的Ctrl C与V,而是一个字一个标点符号慢慢写出来的.我认为这才是是对读者的负责,本教程由技术爱好者成笑笑(博客:http://www.chengxiaoxiao.com/)写作完成. ...

  3. 40多个非常有用的Oracle 查询语句

    给大家介绍是40多个非常有用的Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询.这些是所有Oracle 开发者都必备的技能,所以快快收藏吧! 日期 ...

  4. MYSQL之高级查询

    PHP高级查询 分组查询.联合查询.连接查询.子查询 版权声明:本文为博主原创文章,未经博主允许不得转载.

  5. PHP中的strtotime()对于31日求上个月有问题

    原文出处 <?php $date = "2012-07-31"; $date_unix = strtotime($date); $lastmonth = strtotime( ...

  6. html a标签 图片边框和点击后虚线框的有关问题

    html a标签 图片边框和点击后虚线框的问题 一直在在chrome上开发自己的项目,今天上ie和firefix一看,真丑,a标签在使用图片时,多加了蓝色的边框,并且点击后所有a标签都会出现一个虚线框 ...

  7. java的真相

    所谓编译,就是把源代码“翻译”成目标代码——大多数是指机器代码——的过程.针对Java,它的目标代码不是本地机器代码,而是虚拟机代码. 编译原理里面有一个很重要的内容是编译器优化.所谓编译器优化是指, ...

  8. 使用DataList 分页方法

    什么是DataList我想应该不需要解释了,接下来分享本人在项目里使用到的通过DataList进行分页展示方法. 首先在ASPX页面添加一个DataList(后面都简称DL)控件,示例代码如下: &l ...

  9. 浅谈iOS开发的协议(protocol)和代理(delegate)

    协议和代理对于一个新手来说确实不讨好理解,也有很多的iOS开发的老手对此是懂非懂的.网上的很多博文只是讲了怎么使用,并没有说的很明白.下面我谈一下我的理解. 1.你要先搞明白,协议和代理为什么会出现, ...

  10. Constant is not finite! That's illegal. constant:inf'

    原本使用正常的情况, 切换为测试库突然出现这个错误, 网上搜索并排查后得出导致这个问题的原因: (1)就是你的除数为0(2)除数或者被除数为null 找出你出错的界面, 并打断点, 看看是否出现上面两 ...