splay2(区间修改+内存回收)
poj3580
要求写一种数据结构;
对一个序列进行
区间增减(add); 区间翻转(reverse); 区间移动(revolve);
插入(insert); 删除(delete); 求区间最小值(min);
据说各种方法都可以做,但是只学了splay;
对于(revolve)是指,将区间[x,y]旋转t次
{1,2,3,4,5} revolve(2,4,2); {1,2,3,4,5}->{1,4,2,3,5}->{1,3,2,4,5}
PS:小常数rotate & splay操作(zuo si)
void small_const_rotate(int x,int d){
int y=T[x].fa;
T[y].son[!d]=T[x].son[d];
T[T[x].son[d]].fa=y;
if(T[y].fa) T[T[y].fa].son[T[T[y].fa].son[]==y]=x;
T[x].fa=T[y].fa,T[x].son[d]=y;
T[y].fa=x;
up(y);
}
small_const_rotate
void small_const_splay(int x,int goal){//伸展操作,将x调整到goal下面
lazy(x);
while(T[x].fa!=goal){
if(T[T[x].fa].fa==goal){
lazy(T[x].fa),lazy(x);
rotate(x,T[T[x].fa].son[]==x);//这题有反转操作,需要先lazy,在判断左右孩子
}
else{
lazy(T[T[x].fa].fa),lazy(T[x].fa),lazy(x);//这题有反转操作,需要先lazy,在判断左右孩子
int y=T[x].fa , k=(T[T[y].fa].son[]==y);
if(T[y].son[k]==x)rotate(x,k^),rotate(x,k);//两个方向不同,则先左旋再右旋
else rotate(y,k),rotate(x,k); //两个方向相同,相同方向连续两次
}
}
up(x);
if(goal==) root=x;
}
small_const_splay
模板如下:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define file(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
#define Front T[T[root].son[1]].son[0]
#define ls T[x].son[0]
#define rs T[x].son[1]
const int MAXN=+;
const int INF=(int)2e9;
int a[MAXN],n,m;
struct splay_tree{
struct Node{
int son[],fa,key,size,add,rev,min;
void init(){
son[]=son[]=fa=key=size=add=rev=;
min=INF;
}
}T[MAXN];
int root,tot,s[MAXN],top;//内存池、内存池容量 void NewNode(int &x,int fa,int key){
if(top)x=s[top--];
else x=++tot;
ls=rs=;
T[x].fa=fa,T[x].size=;
T[x].add=T[x].rev=;
T[x].key=T[x].min=key;
} void up_rev(int x){
if(x==)return;
swap(ls,rs);
T[x].rev^=;
} void up_add(int x,int val){
if(x==)return;
T[x].add+=val, T[x].key+=val, T[x].min+=val;
} void up(int x){
T[x].size=T[ls].size+T[rs].size+;
T[x].min=T[x].key;
if(ls)T[x].min=min(T[x].min,T[ls].min);
if(rs)T[x].min=min(T[x].min,T[rs].min);
} void lazy(int x){
if(T[x].rev){
up_rev(ls); up_rev(rs);
T[x].rev=;
}
if(T[x].add){
up_add(ls,T[x].add);
up_add(rs,T[x].add);
T[x].add=;
}
} void build(int &x,int l,int r,int fa){
if(l>r)return;
int mid=(l+r)>>;
NewNode(x,fa,a[mid]);
build(ls,l,mid-,x);
build(rs,mid+,r,x);
up(x);
} void init(){
root=tot=top=;
T[root].init();
NewNode(root,,INF);
NewNode(T[root].son[],root,INF);
build(Front,,n,T[root].son[]);
up(T[root].son[]);
up(root);
} void rotate(int x,int k){
int y=T[x].fa,z=T[y].fa;
T[y].son[k^]=T[x].son[k] ,T[T[x].son[k]].fa=y;
T[x].son[k]=y ,T[y].fa=x;
T[z].son[T[z].son[]==y]=x ,T[x].fa=z;
up(y);
} void splay(int x,int goal){
if(x==goal)return;
while(T[x].fa!=goal){
int y=T[x].fa,z=T[y].fa;
lazy(z),lazy(y),lazy(x);
int rx=T[y].son[]==x ,ry=T[z].son[]==y;
if(z==goal)rotate(x,rx);
else{
if(rx==ry)rotate(y,ry);
else rotate(x,rx);
rotate(x,ry);
}
}
up(x);
if(goal==)root=x;
} int kth(int x,int k){
lazy(x);
int s=T[ls].size+;
if(s==k)return x;
if(s>k)return kth(ls,k);
else return kth(rs,k-s);
} void erase(int x){
if(x){
s[++top]=x;
erase(ls);
erase(rs);
}
} void update_add(int l,int r,int val){
splay(kth(root,l),);
splay(kth(root,r+),root);
up_add(Front,val);
up(T[root].son[]);
up(root);
} void update_reverse(int l,int r){
splay(kth(root,l),);
splay(kth(root,r+),root);
up_rev(Front);
up(T[root].son[]);
up(root);
} void update_revolve(int l,int r,int t){
int len=r-l+; t=(t%len+len)%len;if(t==) return;
int k=r-t+;
splay(kth(root,k),);
splay(kth(root,r+),root);
int tmp=Front;
Front=;
up(T[root].son[]);
up(root);
splay(kth(root,l),);
splay(kth(root,l+),root);
Front=tmp;
T[Front].fa=T[root].son[];
up(T[root].son[]);
up(root);
} void update_insert(int x,int P){
splay(kth(root,x+),);
splay(kth(root,x+),root);
NewNode(Front,T[root].son[],P);
up(T[root].son[]);
up(root);
} void update_delete(int x){
splay(kth(root,x),);
splay(kth(root,x+),root);
erase(Front);
T[Front].fa=;
Front=;
up(T[root].son[]);
up(root);
} int query_min(int l,int r){
splay(kth(root,l),);
splay(kth(root,r+),root);
return T[Front].min;
} void work(){
char str[];int x,y,D,P,T;
scanf("%d",&n);for(int i=;i<=n;i++)scanf("%d",&a[i]);
init();
for(scanf("%d",&m);m--;){
scanf("%s%d",str,&x);
if(strcmp(str,"DELETE")==)update_delete(x);
else if(strcmp(str,"INSERT")==)scanf("%d",&P),update_insert(x,P);
else if(strcmp(str,"ADD")==)scanf("%d%d",&y,&D),update_add(x,y,D);
else if(strcmp(str,"REVERSE")==)scanf("%d",&y),update_reverse(x,y);
else if(strcmp(str,"MIN")==)scanf("%d",&y),printf("%d\n",query_min(x,y));
else if(strcmp(str,"REVOLVE")==)scanf("%d%d",&y,&T),update_revolve(x,y,T);
}
}
}poj3580;
int main(){poj3580.work();return ;}
poj3580
splay2(区间修改+内存回收)的更多相关文章
- linux内存源码分析 - 内存回收(匿名页反向映射)
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 概述 看完了内存压缩,最近在看内存回收这块的代码,发现内容有些多,需要分几块去详细说明,首先先说说匿名页的反向映 ...
- Android 操作系统的内存回收机制(转载)
Android 操作系统的内存回收机制(转载) Android APP 的运行环境 Android 是一款基于 Linux 内核,面向移动终端的操作系统.为适应其作为移动平台操作系统的特殊需要,谷歌对 ...
- hiho一下20周 线段树的区间修改
线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了 ...
- Android内存回收机制
退出但不关闭: 这是Android对于Linux的优化.当 Android 应用程序退出时,并不清理其所占用的内存,Linux 内核进程也相应的继续存在,所谓“退出但不关闭”.从而使得用户调用程序时能 ...
- Java内存回收机制
在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方面工作都是由JVM自动完成的,降低了Java程序员的学习难度,避免了像C/C++直接操作内存的危险.但是,也正 ...
- hihoCode 1078 : 线段树的区间修改
#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题 ...
- memcache的内存回收机制
memcache不会释放内存,而是重新利用. 在缓存的清除方面,memcache是不释放已分配内存.当已分配的内存所在的记录失效后,这段以往的内存空间,memcache只会重复利用. memcache ...
- Java的内存回收机制
原文出处: cnblogs-小学徒V 在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方面工作都是由JVM自动完成的,降低了Java程序员的学习难度,避免了像C ...
- [转载]Java的内存回收机制
转自:http://www.admin10000.com/document/1671.html 在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方面工作都是由J ...
随机推荐
- react-react中的css+评论组件
一个小案例,巩固有状态组件和无状态组件的使用 通过for循环生成多个组件 数据: CommentList = [ { user: '张三', content: '哈哈,沙发' }, { user: ' ...
- OpenCV3.2.0+VS2015开发环境配置
vs2015安装可参考:https://www.jianshu.com/p/391e67529bd3 OpenCV3.2.0配置可参考:https://www.jianshu.com/p/026093 ...
- 百度网盘无vip高速下载的方法
我拿的是谷歌浏览器做实验 首先下载一个可以改user-agent的插件 我chorm里面下载的是User-Agent Switcher for Chrome插件 将百度网盘的url地址中的baidu. ...
- 题解【AcWing95】费解的开关
题面 一道非常好的递推练习题. 我们考虑每次枚举第一行的操作,由上一行的状态递推出下一行的状态,最后判断最后一行是否全部为 \(1\) 即可. 实现代码时要注意一些细节问题. #include < ...
- linux用户管理相关命令
查看用户以及用户组: cat /etc/group [root@izuf60kjjii4iwkhdsly3bz html]# cat /etc/group 内容具体分析 /etc/group ...
- 记录 Docker 的学习过程 (单机编排)
容器的编排 什么是容器的编排?就是让容器有序的启动并在启动的过程加以控制 docker-compose -f bainpaiwenjian.yul up 如果编排文件为默认名称docker-compo ...
- Vue ui创建项目
vue-cli 3.0 版本为我们提供了集 创建.管理.分析 为一体的可视化界面vue UI,一个可视化项目管理器 一.打开终端,安装最新vue-cli npm install -g @vue/cli ...
- mac 命令行下 vim 的使用
vi/vim 使用实例 使用 vi 来建立名为 test.txt 的文件 vi test.txt1按下 ESC 按钮回到一般模式 在一般模式中按下 :wq 储存后离开 vi 基本上 vi/vim 共分 ...
- spark 为什么要用broadcast[转]
为什么要用broadcast? 21down vote If you have huge array that is accessed from Spark Closures, for example ...
- linux centos7环境下安装apache2.4+php5.6+mysql5.6 安装及踩坑集锦(二)
linux centos7环境下安装apache2.4+php5.6+mysql5.6 安装及踩坑集锦(二) 安装apache web容器 . yum方式安装apache 注意apache在linux ...