郁闷的出纳员 (splay的区间标记模板,删除区间,add标记,类似线段树)
来源:互联网 发布:东华金云网络股份公司 编辑:程序博客网 时间:2024/05/29 14:49
往事不堪回首。。
这个题目花了2天时间才A了。
思路照搬SnowyJone大牛:http://www.cnblogs.com/w007878/p/3453023.html Orz。。
此处可找到数据:http://tieba.baidu.com/p/1217076472
真是虐心的两天,整个人都瘦了。。
当然也算值了,为的就是splay的模板大计!
操作中较为难办的就是相同数和删除区间。
相同数解决方法:保证每个数都不同,用num记录其个数
删除区间[l, r]:实际上是将l的前驱p,r的后继q,将p移动到q的子节点,直接删除p的右子树,然后更新即可。相比对序列操作的l 和 r可能不存在,需要特殊处理一下。
再者就是各种细节:
1. 初始工资小于MIN的不算踢出的。。
2. 各种PUSHUP,PUSHDOWN注意。
转载 : http://www.cnblogs.com/Mathics/p/3978047.html
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cstdlib>#include <cmath>#include <utility>#include <vector>#include <queue>#include <map>#include <set>#define max(x,y) ((x)>(y)?(x):(y))#define min(x,y) ((x)>(y)?(y):(x))#define INF 0x3f3f3f3f#define MAXN 100005using namespace std;int cnt, rt;int Add[MAXN],ans;struct Tree{ int key, num, size, fa, son[2];}T[MAXN];inline void PushUp(int x){ T[x].size=T[T[x].son[0]].size+T[T[x].son[1]].size+T[x].num;}inline void PushDown(int x){ if(Add[x]) { if(T[x].son[0]) { T[T[x].son[0]].key+=Add[x]; Add[T[x].son[0]]+=Add[x]; } if(T[x].son[1]) { T[T[x].son[1]].key+=Add[x]; Add[T[x].son[1]]+=Add[x]; } Add[x]=0; }}inline int Newnode(int key, int fa) //新建一个节点并返回{ ++cnt; T[cnt].key=key; T[cnt].num=T[cnt].size=1; T[cnt].fa=fa; T[cnt].son[0]=T[cnt].son[1]=0; return cnt;}inline void Rotate(int x, int p) //0左旋 1右旋{ int y=T[x].fa; PushDown(y); PushDown(x); T[y].son[!p]=T[x].son[p]; T[T[x].son[p]].fa=y; T[x].fa=T[y].fa; if(T[x].fa) T[T[x].fa].son[T[T[x].fa].son[1] == y]=x; T[x].son[p]=y; T[y].fa=x; PushUp(y); PushUp(x);}void Splay(int x, int To) //将x节点移动到To的子节点中{ while(T[x].fa != To) { if(T[T[x].fa].fa == To) Rotate(x, T[T[x].fa].son[0] == x); else { int y=T[x].fa, z=T[y].fa; int p=(T[z].son[0] == y); if(T[y].son[p] == x) Rotate(x, !p), Rotate(x, p); //之字旋 else Rotate(y, p), Rotate(x, p); //一字旋 } } if(To == 0) rt=x;}int GetPth(int p, int To) //返回第p小的节点 并移动到To的子节点中{ if(!rt || p > T[rt].size) return 0; int x=rt; while(x) { PushDown(x); if(p >= T[T[x].son[0]].size+1 && p <= T[T[x].son[0]].size+T[x].num) break; if(p > T[T[x].son[0]].size+T[x].num) { p-=T[T[x].son[0]].size+T[x].num; x=T[x].son[1]; } else x=T[x].son[0]; } Splay(x, 0); return x;}int Find(int key) //返回值为key的节点 若无返回0 若有将其转移到根处{ if(!rt) return 0; int x=rt; while(x) { PushDown(x); if(T[x].key == key) break; x=T[x].son[key > T[x].key]; } if(x) Splay(x, 0); return x;}int Prev() //返回根节点的前驱 非重点{ if(!rt || !T[rt].son[0]) return 0; int x=T[rt].son[0]; while(T[x].son[1]) { PushDown(x); x=T[x].son[1]; } Splay(x, 0); return x;}int Succ() //返回根结点的后继 非重点{ if(!rt || !T[rt].son[1]) return 0; int x=T[rt].son[1]; while(T[x].son[0]) { PushDown(x); x=T[x].son[0]; } Splay(x, 0); return x;}void Insert(int key) //插入key值{ if(!rt) rt=Newnode(key, 0); else { int x=rt, y=0; while(x) { PushDown(x); y=x; if(T[x].key == key) { T[x].num++; T[x].size++; break; } T[x].size++; x=T[x].son[key > T[x].key]; } if(!x) x=T[y].son[key > T[y].key]=Newnode(key, y); Splay(x, 0); }}void Delete(int l, int r) //删除值在[l, r]中的节点{ if(!Find(l)) Insert(l), ans--; int p=Prev(); if(!Find(r)) Insert(r), ans--; int q=Succ(); if(!p && !q) { ans+=T[rt].size; rt=0; return; } if(!p) { ans+=T[T[rt].son[0]].size; T[rt].son[0]=0; PushUp(rt); return; } if(!q) { Splay(p, 0); ans+=T[T[rt].son[1]].size; T[rt].son[1]=0; PushUp(rt); return; } Splay(p, q); if(T[p].son[1]) ans+=T[T[p].son[1]].size; T[p].son[1]=0; PushUp(p); PushUp(q);}int N, MIN, k;char ch;int main(){ scanf("%d %d", &N, &MIN); while(N--) { scanf(" %c %d", &ch, &k); switch (ch) { case 'I': if(k >= MIN) Insert(k); break; case 'A': T[rt].key+=k; Add[rt]+=k; break; case 'S': T[rt].key-=k; Add[rt]-=k; Delete(-INF, MIN-1); break; case 'F': if(T[rt].size-k+1>0) printf("%d\n", T[GetPth(T[rt].size-k+1, 0)].key); else printf("-1\n"); } } printf("%d\n", ans); return 0;}
0 0
- 郁闷的出纳员 (splay的区间标记模板,删除区间,add标记,类似线段树)
- bzoj1503 [NOI2004]郁闷的出纳员(名次树+懒惰标记)
- 线段树模板(区间和+区间最大值 + LAZY标记)
- 郁闷的出纳员(splay)
- hdu-4587-线段树的区间操作- lazy标记
- SKYLINE uva+线段树+区间的修改+lazy标记
- [线段树 标记] BZOJ 3226 [Sdoi2008]校门外的区间
- 郁闷的出纳员 ( splay )
- 线段树 (区间修改 区间查询 延迟标记)
- 线段树区间更新模板(lazy延迟标记)(1698)
- hihocoder 1080 更为复杂的买卖房屋姿势(线段树经典操作,区间修改,add+set标记)
- 线段树1(带懒惰标记的区间更新和整棵树的查询)
- UVA 11402 - Ahoy, Pirates!(线段树区间更新(标记重叠的处理))
- HDU 1698 Just a Hook(线段树的区间更新《标记》)
- hdu1689-Just a Hook-线段树-整段区间的替换(延迟标记)
- 【NOI2004】郁闷的出纳员(splay)
- bzoj1503 [NOI2004]郁闷的出纳员(splay)
- [BZOJ1503][NOI2004]郁闷的出纳员(平衡树splay)
- 前端小白进阶Day4-结合盒子模型发布一张卡片
- Java求最大公约数和最小公倍数
- 前端新手必看JavaScript常用代码总结
- 函数声明和函数表达式的异同
- 抽象类与接口
- 郁闷的出纳员 (splay的区间标记模板,删除区间,add标记,类似线段树)
- Maven安装与环境配置
- 2017.04.18盒子任务
- 手工添加MFC list control 的 双击消息响应函数
- Redis缓存技术学习系列之发布订阅
- dijkstra c++实现
- python学习路线
- [LeetCode]237. Delete Node in a Linked List
- Spring之AOP