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 ...
随机推荐
- FreeBSD更换默认csh为bash
1.安装bash cd /usr/ports/shells/bash make install 2.切换chsh(change shell) chsh -s /usr/local/bin/bash
- LCA问题
基本概念 LCA:树上的最近公共祖先,对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. RMQ:区间最小值查询问题.对于长度为n的 ...
- enableEventValidation
回发或回调参数无效.在配置中使用 <pages enableEventValidation="true"/> 或在页面中使用 <%@ Page EnableEve ...
- linux du 显示目录下的各个子目录的大小
use command du display estimate file space usage size of subdirectories [oracle@ahjcyl-db backup]$ ...
- maven 创建的符号连接命令
E:\Joyplus\src\main\webapp\WEB-INF>mklink /d lib ..\..\..\.\..\target\ediHelperSuite-0.5\WEB-INF\ ...
- 防范DDOS攻击脚本
防范DDOS攻击脚本 #防止SYN攻击 轻量级预防 iptables -N syn-flood iptables -A INPUT -p tcp --syn -j syn-flood iptables ...
- c++相关知识回顾
1.typedef typedef用来定义同类型的同义词.如: typedef unsingned int size_t; typedef int ptrdiff_t; typedef T * ite ...
- Centos安装编译环境
众所周知,在安装完Centos完了以后,是没有编译环境的,我自己挂上光盘,手动安装解决了几十的依赖关系,在配置些软件时,还是经常报些依赖软件包的缺失,很是头疼,后来百度了下centos需要装的编译环境 ...
- 不为人知的Locked
在属性面板上,有一个Locked属性,什么时候添加上去的,真是没有注意到,它的说明为:确定是否可以移动控件或调整控件的大小,默认是为false的,设置为true以后,当前选中的控件会在左上角出现一个锁 ...
- css 多出一行或多行后显示...的方法
一行超出显示... .mui-ellipsis { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } 两行超出的显示. ...