hdu 2871 Memory Control

题意:就是对一个区间的四种操作,NEW x,占据最左边的连续的x个单元,Free x 把x单元所占的连续区间清空 , Get x 把第x次占据的区间输出来, R 清空整个区间。

解题思路:这个题就是一个区间合并,以前用线段树写的,拿来练练splay。要记录的是区间最大的连续空格,要维护这个最值,需要两个辅助的值,该区间左边连续的最值和右边连续的最值。更新的时候仔细就好了,其他就是splay的常规操作的。还有就是记录占据的连续区间和查找占据的连续区间用个vector,二分查找,插入就好了。在清空整个区间时,用update,不要重建一棵树。

(看似简单,我调了一天啊。。起初是push_up写不好,调很久没弄出来,后来过了样例,一直TLE。。还以为是效率不够高,第二天才发现是内存池的tot没清零)

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std ; vector< pair<int,int> > vec ;
const int maxn = 55555 ; int tot , n , m ; int lm[maxn] , rm[maxn] , mm[maxn] , col[maxn] , val[maxn] ;
int son[2][maxn] , fa[maxn] , size[maxn] , pos[maxn] ; void new_node ( int l , int r ) {
size[tot] = 1 ;
son[0][tot] = son[1][tot] = fa[tot] = -1 ;
lm[tot] = rm[tot] = mm[tot] = r - l + 1 ;
col[tot] = 1 , val[tot] = 1 ;
if ( l == 0 ) col[tot] = -1 , lm[tot] = 0 , rm[tot] -- , mm[tot] -- ;
if ( r == n + 1 ) col[tot] = -1 , rm[tot] = 0 , lm[tot] -- , mm[tot] -- ;
if ( ( ( l + r ) >> 1 == 0 ) || ( ( l + r ) >> 1 == n + 1 ) ) val[tot] = 0 ;
tot ++ ;
} void push_down ( int rt ) {
if ( col[rt] != -1 ) {
int ls = son[0][rt] , rs = son[1][rt] ;
val[ls] = val[rs] = col[rt] ;
if ( ls != -1 ) {
col[ls] = col[rt] ;
lm[ls] = rm[ls] = mm[ls] = size[ls] * col[rt] ;
}
if ( rs != -1 ) {
col[rs] = col[rt] ;
lm[rs] = rm[rs] = mm[rs] = size[rs] * col[rt] ;
}
col[rt] = -1 ;
}
} void push_up ( int rt ) {
size[rt] =1 ;
mm[rt] = lm[rt] = rm[rt] = val[rt] ;
int ls = son[0][rt] , rs = son[1][rt] ;
if ( val[rt] ) {
if ( ls == -1 ) lm[rt] = 1 + ( rs == -1 ? 0 : lm[rs] ) ;
if ( rs == -1 ) rm[rt] = 1 + ( ls == -1 ? 0 : rm[ls] ) ;
}
if ( ls != -1 ) {
lm[rt] = lm[ls] ;
mm[rt] = max ( mm[ls] , rm[ls] + val[rt] ) ;
if ( lm[ls] == size[ls] ) lm[rt] += val[rt] , mm[rt] += val[rt] ;
size[rt] += size[ls] ;
}
if ( rs != -1 ) {
rm[rt] = rm[rs] ;
mm[rt] = max ( mm[rt] , max ( mm[rs] , lm[rs] + val[rt] ) ) ;
if ( rm[rs] == size[rs] ) rm[rt] += val[rt] , mm[rt] = max ( mm[rt] , rm[rs] + val[rt] ) ;
size[rt] += size[rs] ;
}
if ( ls != -1 && rs != -1 && val[rt] ) {
mm[rt] = max ( mm[rt] , rm[ls] + lm[rs] + 1 ) ;
if ( lm[ls] == size[ls] ) lm[rt] = lm[ls] + 1 + lm[rs] ;
if ( rm[rs] == size[rs] ) rm[rt] = rm[rs] + 1 + rm[ls] ;
}
} int build ( int l , int r ) {
if ( l > r ) return -1 ;
int mid = ( l + r ) >> 1 ;
new_node ( l , r ) ;
int temp = tot - 1 ;
son[0][temp] = build ( l , mid - 1 ) ;
if ( son[0][temp] != -1 ) fa[son[0][temp]] = temp , size[temp] += size[son[0][temp]] ;
son[1][temp] = build ( mid + 1 , r ) ;
if ( son[1][temp] != -1 ) fa[son[1][temp]] = temp , size[temp] += size[son[1][temp]] ;
return temp ;
} void rot ( int rt , int c ) {
int y = fa[rt] , z = fa[y] ;
push_down ( y ) , push_down ( rt ) ;
son[!c][y] = son[c][rt] ;
if ( son[c][rt] != -1 ) fa[son[c][rt]] = y ;
fa[rt] = z ;
if ( z != -1 ) {
if ( y == son[0][z] ) son[0][z] = rt ;
else son[1][z] = rt ;
}
son[c][rt] = y , fa[y] = rt ;
push_up ( y ) ;
} void splay ( int rt , int to ) {
push_down ( rt ) ;
while ( fa[rt] != to ) {
if ( fa[fa[rt]] == to ) rot ( rt , rt == son[0][fa[rt]] ) ;
else {
int y = fa[rt] , z = fa[y] ;
if ( rt == son[0][y] ) {
if ( y == son[0][z] ) rot ( y , 1 ) , rot ( rt , 1 ) ;
else rot ( rt , 1 ) , rot ( rt , 0 ) ;
}
else {
if ( y == son[1][z] ) rot ( y , 0 ) , rot ( rt , 0 ) ;
else rot ( rt , 0 ) , rot ( rt , 1 ) ;
}
}
}
push_up ( rt ) ;
} int find ( int rt , int key ) {
int cnt = 0 ;
if ( son[0][rt] != -1 ) cnt = size[son[0][rt]] ;
if ( cnt + 1 == key ) return rt ;
if ( cnt >= key ) return find ( son[0][rt] , key ) ;
return find ( son[1][rt] , key - cnt - 1 ) ;
} int update ( int l , int r , int c , int rt ) {
l ++ , r ++ ;
int temp = pos[l-1] ;
splay ( temp , -1 ) ;
rt = temp ;
temp = pos[r+1] ;
splay ( temp , rt ) ;
temp = son[0][temp] ;
col[temp] = val[temp] = c ;
lm[temp] = rm[temp] = mm[temp] = size[temp] * c ;
push_up ( fa[temp] ) ;
push_up ( fa[fa[temp]] ) ;
return rt ;
} int search ( int rt , int key , int rk ) {
push_down ( rt ) ;
int ls = son[0][rt] , rs = son[1][rt] ;
if ( ls != -1 && mm[ls] >= key ) {
return search ( ls , key , rk ) ;
}
if ( val[rt] ) {
int cnt = 1 ;
if ( ls != -1 ) cnt += rm[ls] ;
if ( rs != -1 ) cnt += lm[rs] ;
if ( cnt >= key ) {
int pos = rk ;
if ( ls != -1 ) pos += size[ls] ;
return pos - rm[ls] ;
}
}
return search ( rs , key , rk + 1 + ( ls == -1 ? 0 : size[ls] ) ) ;
} int bin ( int key ) {
int l = 0 , r = vec.size () - 1 ;
while ( l <= r ) {
int m = ( l + r ) >> 1 ;
if ( vec[m].second >= key ) r = m - 1 ;
else l = m + 1 ;
}
return r + 1 ;
} int bin2 ( int key ) {
int l = 0 , r = vec.size () - 1 ;
while ( l <= r ) {
int m = ( l + r ) >> 1 ;
if ( vec[m].second <= key ) l = m + 1 ;
else r = m - 1 ;
}
return l ;
} int get_num()
{
char a ;
int num = 0 ;
int flag = 1 ;
while ( a = getchar() , ( a < '0' || a > '9' ) && a != '-' ) ;
if ( a == '-' ) flag = -1 ;
else num = a - '0' ;
while (( a = getchar()) != ' ' && a != '\n' )
num = num * 10 + (a-'0') ;
return num * flag ;
} int main () {
char op[11] ;
int a , b , i ;
while ( scanf ( "%d%d" , &n , &m ) != EOF ) {
tot = 0 ;
int root = build ( 0 , n + 1 ) ;
for ( i = 1 ; i <= n + 2 ; i ++ ) pos[i] = find ( root , i ) ;
pair<int,int> u ;
vec.clear () ;
while ( m -- ) {
scanf ( "%s" , op ) ;
if ( op[0] == 'R' ) {
root = update ( 1 , n , 1 , root ) ;
vec.clear () ;
puts ( "Reset Now" ) ;
}
else if ( op[0] == 'N' ) {
a = get_num () ;
if ( mm[root] < a ) puts ( "Reject New" ) ;
else {
int l = search ( root , a , 0 ) ;
printf ( "New at %d\n" , l ) ;
int r = l + a - 1 ;
root = update ( l , r , 0 , root ) ;
u = make_pair ( l , r ) ;
l = bin2 ( r ) ;
vec.insert ( vec.begin () + l , u ) ;
}
}
else if ( op[0] == 'F' ) {
a = get_num () ;
int k = bin ( a ) ;
if ( k == vec.size () || vec[k].first > a ) puts ( "Reject Free" ) ;
else {
printf ( "Free from %d to %d\n" , vec[k].first , vec[k].second ) ;
root = update ( vec[k].first , vec[k].second , 1 , root ) ;
vec.erase ( vec.begin () + k , vec.begin () + k + 1 ) ;
}
}
else {
a = get_num () ;
if ( a > vec.size () ) puts ( "Reject Get" ) ;
else printf ( "Get at %d\n" , vec[a-1].first ) ;
}
}
puts ( "" ) ;
}
}
/*
10 2
N 9
N 1
*/

hdu 2871 Memory Control(伸展树splay tree)的更多相关文章

  1. hdu 2871 Memory Control(线段树)

    题目链接:hdu 2871 Memory Control 题目大意:模拟一个内存分配机制. Reset:重置,释放全部空间 New x:申请内存为x的空间,输出左地址 Free x:释放地址x所在的内 ...

  2. HDU 4453 Looploop (伸展树splay tree)

    Looploop Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  3. 树-伸展树(Splay Tree)

    伸展树概念 伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.它由Daniel Sleator和Robert Tarjan创造. (01) 伸展树属于二 ...

  4. 纸上谈兵: 伸展树 (splay tree)[转]

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢!  我们讨论过,树的搜索效率与树的深度有关.二叉搜索树的深度可能为n,这种情况下,每 ...

  5. K:伸展树(splay tree)

      伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(lgN)内完成插入.查找和删除操作.在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使 ...

  6. 高级搜索树-伸展树(Splay Tree)

    目录 局部性 双层伸展 查找操作 插入操作 删除操作 性能分析 完整源码 与AVL树一样,伸展树(Splay Tree)也是平衡二叉搜索树的一致,伸展树无需时刻都严格保持整棵树的平衡,也不需要对基本的 ...

  7. 【BBST 之伸展树 (Splay Tree)】

    最近“hiho一下”出了平衡树专题,这周的Splay一直出现RE,应该删除操作指针没处理好,还没找出原因. 不过其他操作运行正常,尝试用它写了一道之前用set做的平衡树的题http://codefor ...

  8. 伸展树(Splay tree)的基本操作与应用

    伸展树的基本操作与应用 [伸展树的基本操作] 伸展树是二叉查找树的一种改进,与二叉查找树一样,伸展树也具有有序性.即伸展树中的每一个节点 x 都满足:该节点左子树中的每一个元素都小于 x,而其右子树中 ...

  9. 伸展树 Splay Tree

    Splay Tree 是二叉查找树的一种,它与平衡二叉树.红黑树不同的是,Splay Tree从不强制地保持自身的平衡,每当查找到某个节点n的时候,在返回节点n的同时,Splay Tree会将节点n旋 ...

随机推荐

  1. KindEditor - 代码高亮

    *:插入数据库的数据,不用转义,KE已经自动转义过了. 调用的时候使用引入代码的css: 显示代码的页面:

  2. c++,内联成员函数

    内联成员函数有两程方式实现内联成员函数1)在声名成员函数的同时定义成员函数体2)声明成员函数时,在最前面加上inline关键字在定义成员函数时也在最前面加上inline关键字 建议inline函数在头 ...

  3. 通过SecureCRT和PuTTY连接臻云CentOS版云主机

    原文地址:http://jingyan.baidu.com/article/fa4125acb6648128ac7092dc.html 如何通过SecureCRT和PuTTY工具远程连接臻云CentO ...

  4. 动态规划---最长上升子序列问题(O(nlogn),O(n^2))

    LIS(Longest Increasing Subsequence)最长上升子序列 或者 最长不下降子序列.很基础的题目,有两种算法,复杂度分别为O(n*logn)和O(n^2) . ******* ...

  5. 【集训笔记】二分图及其应用【HDOJ1068【HDOJ1150【HDOJ1151

    匈牙利算法样例程序 格式说明 输入格式: 第1行3个整数,V1,V2的节点数目n1,n2,G的边数m 第2-m+1行,每行两个整数t1,t2,代表V1中编号为t1的点和V2中编号为t2的点之间有边相连 ...

  6. solrCloud+tomcat+zookeeper配置

    一.环境准备: Solr版本:4.7.0 下载地址:http://www.apache.org/dyn/closer.cgi/lucene/solr/4.7.0 Tomcat版本:6.0.39 下载地 ...

  7. UIScrollView方法 属性详解

    --前言:UIScrollView使用非常广,本文研究UIScrollView各属性和方法,明白它们的意义.作用.在后面的一篇文章有整理UIScrollView一些常见用法以及一些效果的实现思路. - ...

  8. UNIX环境高级编程——进程管理和通信(总结)

    进程管理与通信 进程的管理 进程和程序的区别: 进程: 程序的一次执行过程   动态过程,进程的状态属性会发生变化 程序:存放在磁盘上的指令.数据的有序集合  是个文件,可直观看到 程序program ...

  9. shu_1548 悟空问题(大哥,主妖怪抓走的朋友!)

    http://202.121.199.212/JudgeOnline/problem.php?cid=1078&pid=17 分析:  直接暴力了.. . 代码: #include <s ...

  10. secureCRT登录不上ubuntu,Connection closed

    secureCRT登录不上ubuntu 1.第一个原因是sshd服务没开,或者防火墙没关.装好sshd并打开就好. http://www.cnblogs.com/mylinux/p/5101956.h ...