POJ 3580 (伸展树)
题目链接: http://poj.org/problem?id=3580
题目大意:对一个序列进行以下六种操作。输出MIN操作的结果。
解题思路:
六个操作,完美诠释了伸展树有多么吊。注意,默认使用Lazy标记,在pushdown中维护。
ADD操作:为x~y元素加一个d值。首先用split切出x~y元素。然后改变给切出的root->add,root->min,root->v。再merge进原序列。
REVERSE操作:把x~y元素反转。首先用split切出x~y元素,然后改变root->flip标记。再merge进原序列。
REVOLVE操作:把x~y元素偏移T位。注意T可以为负。负向左,正向右。
首先对T进行修正。T=(T%(r-l+1)+(r-l+1))%(r-l+1)),参考自cxlove大神,这样正负方向就一致了,而且解决了没必要的偏移。
这样问题就转化为把[x,y]序列变成left+[y-T+1,y]+[x,y-T]+right,同样参考自cxlove大神。
那么只要split出[x,y-T]就行了。注意T=0时要特判,不然等于切了个0空间,程序就爆了。
INSERT操作:在第x元素后插入P。首先切出[1,x],然后merge这个新的P元素,再merge右段。
注意一下,虽然伸展树是意义上的BST,但是伸展树一旦为了维护原有序列顺序,则可以不再遵循BST的左<=中<=右原则。
这里的INSERT就是,把P元素merge到右边是防止BST维护改变顺序(merge只对left进行BST维护)。
DELETE操作:切出左右两段,merge即可。
MIN操作:求x~y元素最小值。依赖于pushup(也就是maintain),每次变动都要维护root-v,root->left,root->right三部分的最小值。
首先切出[x,y],root->minn就是结果。
额外吐槽一下build操作,首先在0号位置加一个inf大的前置结点,这样就可以split出[x,y]这个段了,如果没有前置结点,则应该这么切[1,x-1],当x=1时就完蛋了。
build(0,n)。这样0号点就被放在了最左边。build的时候为了保持原序列顺序,根据位置进行二分build。在最初把伸展树的高度给压下去。
因为伸展树的平衡性能实在太差,如果build成链,那么就要完蛋啦。
#include "cstdio"
#include "cstdlib"
#include "time.h"
#include "queue"
#include "vector"
#include "cstring"
using namespace std;
struct node
{
node *ch[];
long long v,s,minn,flip,add;
node() {s=flip=add=;minn=<<;}
void maintain()
{
s=;
s+=ch[]->s;
s+=ch[]->s;
minn=min(v,min(ch[]->minn,ch[]->minn));
}
void push_down()
{
if(flip)
{
flip = ;
swap(ch[], ch[]);
ch[]->flip = !ch[]->flip;
ch[]->flip = !ch[]->flip;
}
if(add)
{
ch[]->add+=add;ch[]->add+=add;
ch[]->v+=add;ch[]->v+=add;
ch[]->minn+=add;ch[]->minn+=add;
add=;
}
}
int cmp(int x)
{
int d = x-ch[]->s;
if(d == ) return -;
return d <= ? : ;
}
};
node *null=new node();
node *root;
node *left,*mid,*right,*oo;
vector<int> ans;
long long arr[];
void rotate(node* &o,int d)
{
node *k=o->ch[d^];o->ch[d^]=k->ch[d];k->ch[d]=o;
o->maintain();k->maintain();
o=k;
}
void splay(node* &o,int k)
{
o->push_down();
int d=o->cmp(k);
if(d==) k-=o->ch[]->s+;
if(d!=-)
{
node *p=o->ch[d];
p->push_down();
int d2=p->cmp(k);
if(d2!=-)
{
int k2=(d2==?k:k-p->ch[]->s-);
splay(p->ch[d2],k2);
if(d==d2) rotate(o,d^);else rotate(o->ch[d],d);
}
rotate(o,d^);
}
}
node *merge(node* left,node *right)
{
splay(left,left->s);
left->ch[]=right;
left->maintain();
return left;
}
void split(node *o, int k, node *&left, node *&right)
{
splay(o, k);
left = o;
right = o->ch[];
o->ch[] = null;
left->maintain();
}
void build(int l,int r,node* &o)
{
if(l>r) return;
int mid=(l+r)>>;
o=new node;o->v=arr[mid];o->minn=arr[mid];o->s=;o->ch[]=o->ch[]=null;
build(l,mid-,o->ch[]);
build(mid+,r,o->ch[]);
o->maintain();
}
void INSERT(int x,int v)
{
split(root,x+,left,oo);
node *tt=new node;
tt->v=v;tt->s=;tt->minn=v;tt->ch[]=tt->ch[]=null;
root=merge(merge(left,tt),oo);
}
void DELETE(int x)
{
split(root,x,left,oo);
split(oo,,mid,right);
root=merge(left,right);
}
void MIN(int a,int b)
{
split(root,a,left,oo);
split(oo,b-a+,mid,right);
printf("%lld\n",mid->minn);
root=merge(merge(left,mid),right);
}
void REVOLVE(int a,int b,int c)
{
if(!c) return;
node *tt;
split(root,a,left,oo);
split(oo,b-a+,mid,right); //切出[a,b]
split(mid,b-c-a+,tt,oo);//切出[a,b-c]
tt=merge(oo,tt);//合并即可
root=merge(merge(left,tt),right);
}
void ADD(int a,int b,int c)
{
//切出[a,b]
if(!c) return;
split(root,a,left,oo);
split(oo,b-a+,mid,right);
mid->add+=c;
mid->v+=c;
mid->minn+=c;
root=merge(merge(left,mid),right);
}
void REVERSE(int a,int b)
{
split(root,a,left,oo);
split(oo,b-a+,mid,right);
mid->flip^=;
root=merge(merge(left,mid),right);
}
int main()
{
//freopen("0.in","r",stdin);
//freopen("0.out","w",stdout);
int n,m,l,r,x;
char cmd[];
arr[]=<<;//前置结点防止干扰
while(scanf("%d",&n)!=EOF)
{
for(int i=;i<=n;i++)
scanf("%lld",&arr[i]);
build(,n,root);
scanf("%d",&m);
while(m--)
{
scanf("%s",cmd);
if(!strcmp(cmd,"ADD"))
{
scanf("%d%d%d",&l,&r,&x);
ADD(l,r,x);
}
if(!strcmp(cmd,"REVERSE"))
{
scanf("%d%d",&l,&r);
REVERSE(l,r);
}
if(!strcmp(cmd,"REVOLVE"))
{
scanf("%d%d%d",&l,&r,&x);
REVOLVE(l,r,(x%(r-l+)+(r-l+))%(r-l+));
}
if(!strcmp(cmd,"INSERT"))
{
scanf("%d%d",&l,&x);
INSERT(l,x);
}
if(!strcmp(cmd,"DELETE"))
{
scanf("%d",&l);
DELETE(l);
}
if(!strcmp(cmd,"MIN"))
{
scanf("%d%d",&l,&r);
MIN(l,r);
}
}
root=left=right=oo=null;
}
}
13476518 | neopenx | 3580 | Accepted | 8680K | 1047MS | C++ | 4510B | 2014-09-25 17:10:36 |
POJ 3580 (伸展树)的更多相关文章
- poj 3580 SuperMemo
题目连接 http://poj.org/problem?id=3580 SuperMemo Description Your friend, Jackson is invited to a TV sh ...
- poj_3580 伸展树
自己伸展树做的第一个题 poj 3580 supermemo. 题目大意 对一个数组进行维护,包含如下几个操作: ADD x, y, d 在 A[x]--A[y] 中的每个数都增加d REVERSE ...
- 伸展树Splay
新学的,其实吧,就那么回事.... 看了几天,splay处理序列问题,真的非常厉害,翻转,插入,删除,线段树实现不了的功能,splay用起来很方便. POJ 3580 SuperMemo 这题基本就是 ...
- POJ 3580(SuperMemo-Splay区间加)[template:Splay V2]
SuperMemo Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 11384 Accepted: 3572 Case T ...
- Splay伸展树学习笔记
Splay伸展树 有篇Splay入门必看文章 —— CSDN链接 经典引文 空间效率:O(n) 时间效率:O(log n)插入.查找.删除 创造者:Daniel Sleator 和 Robert Ta ...
- 纸上谈兵:伸展树(splay tree)
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们讨论过,树的搜索效率与树的深度有关.二叉搜索树的深度可能为n,这种情况下,每次 ...
- SplayTree伸展树的非递归实现(自底向上)
Splay Tree 是二叉查找树的一种,它与平衡二叉树.红黑树不同的是,Splay Tree从不强制地保持自身的平衡,每当查找到某个节点n的时候,在返回节点n的同时,Splay Tree会将节点n旋 ...
- 伸展树(一)之 图文解析 和 C语言的实现
概要 本章介绍伸展树.它和"二叉查找树"和"AVL树"一样,都是特殊的二叉树.在了解了"二叉查找树"和"AVL树"之后, ...
- 伸展树(二)之 C++的实现
概要 上一章介绍了伸展树的基本概念,并通过C语言实现了伸展树.本章是伸展树的C++实现,后续再给出Java版本.还是那句老话,它们的原理都一样,择其一了解即可. 目录1. 伸展树的介绍2. 伸展树的C ...
随机推荐
- 百度图片爬虫-python版-如何爬取百度图片?
上一篇我写了如何爬取百度网盘的爬虫,在这里还是重温一下,把链接附上: http://www.cnblogs.com/huangxie/p/5473273.html 这一篇我想写写如何爬取百度图片的爬虫 ...
- 数据结构与算法实验题7.1 M 商人的求救
问题描述:A 国正面临着一场残酷的战争,城市被支持不同领导的两股势力占据,作为一个商人,M先生并不太关心政治,但是他知道局势很严重,他希望你能救他出去.M 先生说:“为了安全起见,我们的路线最多只能包 ...
- java中queue的使用
Queue接口与List.Set同一级别,都是继承了Collection接口.LinkedList实现了Queue接 口.Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类 ...
- 【Python】使用 sphinx 制作简洁而又美观的文档
参考资料: http://zh-sphinx-doc.readthedocs.io/en/latest/tutorial.html http://avnpc.com/pages/writing-bes ...
- 【云计算】Netflix 开源持续交付平台 Spinnaker
oschina 发布于: 2015年11月19日 (0评) 分享到: 收藏 +1 CDS首都在线全球云主机.全球私有网络,开工送礼,免费试用! » 日前,Ne ...
- Apache配置文件中的deny和allow的使用
Apache配置文件中的deny和allow的使用 由于产品的需要,最近在配置apache的负载均衡功能,但是在配置虚拟主机的访问权限的时候我们遇到了一些问题.主要问题是deny和allow的执行顺序 ...
- Android 和iOS中 Gesture 和 Touch
先谈谈在开发中遇到的手势问题: 今天在开发android程序时,在 View.OnTouchListener 的 onTouch(View view, MotionEvent motionEvent) ...
- Linux下配置Tomcat服务器
Linux下配置Tomcat服务器和Windows下其实差不多,可以去官网下载安装包释放或者在线下载,只是当时下载的windows.zip文件,现在下载.tar.gz格式的即可,下面使用命令行的方式安 ...
- 10件在PHP 7中不要做的事情
刚刚在园子里看到一篇特别好的文章,就拿到我的园子里分享了. 1. 不要使用mysql_函数 这一天终于来了,从此你不仅仅“不应该”使用mysql_函数.PHP 7 已经把它们从核心中全部移除了,也就是 ...
- MVC增删改查例子
一.显示用户列表1.新建UserInfoController控制器 public ActionResult Index() { DataTable table = SQLHelper.ExecuteR ...