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 ...
随机推荐
- KMP算法精髓
这个算法的做法就是在部分匹配的时候,常规想法是向后移动一位,但是KMP想法是向后移动n位(n=m-L). 注释:这里m表示已经匹配了的字符的个数,L表示已经匹配了的那些字符组成的这个字符串的前缀和后缀 ...
- 【UER #1】[UOJ#12]猜数 [UOJ#13]跳蚤OS [UOJ#14]DZY Loves Graph
[UOJ#12][UER #1]猜数 试题描述 这一天,小Y.小D.小C正在愉快地玩耍. 小Y是个数学家,他一拍脑袋冒出了一个神奇的完全平方数 n. 小D是个机灵鬼,很快从小Y嘴里套出了 n的值.然后 ...
- Access数据库之偏移注入
/*转载请注明出处:珍惜少年时*/ 偏移注入主要是针对知道表,但是不知道字段的. 这里我已经知道了表明是:sys_admin 可以使用: select exists(selct * from sys_ ...
- HDOJ 1257 (最长字序列问题)
http://acm.hdu.edu.cn/showproblem.php?pid=1257 最少拦截系统 Time Limit: 2000/1000 MS (Java/Others) Memo ...
- Linux_DHCP服务搭建
Linux网络参数的设置 1. 修改主机名 # vim /etc/sysconfig/network NETWORKING=yes HOSTNAME=bj.com 2. 修 ...
- Java获取、删除文件和目录
package javatest; import java.io.File; import java.util.ArrayList; import java.util.regex.Pattern; c ...
- Excel Sheet Column Title & Excel Sheet Column Number
Excel Sheet Column Title Given a positive integer, return its corresponding column title as appear i ...
- #define 的一些用法 以及 迭代器的 [] 与 find()函数的区别
#include "stdafx.h" #include <map> #include <string> #include <iostream> ...
- 跨域请求获取Solr json检索结果并高亮显示
Solr提供了json格式的检索结果,然而在跨域的情况下如何调用呢?我们可以利用jquery提供的jsonp的方式获取Solr检索结果. <script type="text/java ...
- Avisynth + DirectShow + WebCamera 实现Avisynth脚本访问摄像头
准备工作:需要以下三种软件 1.Avisynth_258 安装文件和源码下载地址(Avisynth_258.exe 4.2 MB) http://sourceforge.net/projects/av ...