【平衡二叉树】魔兽争霸
来源:互联网 发布:windows域管理教程 编辑:程序博客网 时间:2024/05/01 15:23
第一次,唯一一次直接把别人的题解复制过来。。只是我SBT还没掌握呀,只懂treap。但是看起来唯一不同之处只是Maintain,虽然他们都说难,但是我想如果只是这一个地方不同的话,应该没有什么问题,能学会。
小 x正在销魂地玩魔兽
他正控制着死亡骑士和 n个食尸鬼(编号1~n)去打猎
死亡骑士有个魔法,叫做“死亡缠绕” ,可以给食尸鬼补充HP战斗过程中敌人会对食尸鬼实施攻击,食尸鬼的HP会减少
小 x希望随时知道自己部队的情况,即HP 值第 k多的食尸鬼有多少 HP,以便决定如何施放魔法
请同学们帮助他:)
小 x向你发出 3种信号: (下划线在输入数据中表现为空格))
A_i_a 表示敌军向第 i 个食尸鬼发出了攻击,并使第 i 个食尸鬼损失了 a 点HP,如果 它的 HP<=0,那么这个食尸鬼就死了(Undead 也是要死的……)。
敌军不会攻击一个已死的食尸鬼。
C_i_a 表示死亡骑士向第i个食尸鬼放出了死亡缠绕, 并使其增加了a点HP。
HP值没有上限。
死亡骑士不会向一个已死的食尸鬼发出死亡缠绕
Q_k 表示小 x向你发出询问
输入(war.in)
第一行,一个正整数 n
以后 n个整数 表示 n个食尸鬼的初始HP 值
接着一个正整数 m
以下 m行 每行一个小 x发出的信号
输出(war.out)
对于小 x的每个询问,输出HP 第 k多的食尸鬼有多少HP,如果食尸鬼总数
不足k个,输出-1。每个一行数。
最后一行输出一个数:战斗结束后剩余的食尸鬼数
唐山一中NOIP2005模拟赛(2) - 3 -
样例
Input
5
1 2 3
4 5
10
Q 2
A 4 6
C 1 4
Q 2
A 2 1
A 3 3
A 1 3
Q 4
C 2 10
Q 1
Output
4
5
-1
11
3
约定
40%的数据 n<=3000 m<=5000
70%的数据 n<=8000 m<=10000
100%的数据 n<=30000 m<=50000
90%的数据随机生成
食尸鬼HP没有上限
数据保证任意时刻食尸鬼的HP值在 longint范围内
数据保证 A和C命令中的食尸鬼是活着的
输入数据中没有多余空格、换行
注意平衡二叉树尽量不要对之直接操作,他是动态的,还要必须满足他的性质,直接对之操作容易破坏其结构。
因此我们增加和减少,都通过Insert和Delete来进行,因为这两个操作都是O(lgn)的,因此在数据不是很大的情况下,已经胜用了。
#include <cstdio>#include <cstring>#include <cstdlib>#include <bitset>const char fi[] = "war.in";const char fo[] = "war.out";const int maxN = 100010;const int MAX = 0x3fffff00;const int MIN = -MAX;int lc[maxN], rc[maxN];int c[maxN], key[maxN], sz[maxN];int n, m, tot, T;void init_file(){ freopen(fi, "r", stdin); freopen(fo, "w", stdout);}inline void R_Rotate(int &T){ int tmp = lc[T]; lc[T] = rc[tmp]; rc[tmp] = T; sz[tmp] = sz[T]; sz[T] = sz[lc[T]] + sz[rc[T]] + 1; T = tmp;}inline void L_Rotate(int &T){ int tmp = rc[T]; rc[T] = lc[tmp]; lc[tmp] = T; sz[tmp] = sz[T]; sz[T] = sz[lc[T]] + sz[rc[T]] + 1; T = tmp;}void Maintain(int &T, bool flag){ if (!flag) { if (sz[lc[lc[T]]] > sz[rc[T]]) R_Rotate(T); else if (sz[lc[rc[T]]] > sz[rc[T]]) { L_Rotate(lc[T]); R_Rotate(T); } else return; } else { if (sz[rc[rc[T]]] > sz[lc[T]]) L_Rotate(T); else if (sz[rc[lc[T]]] > sz[lc[T]]) { R_Rotate(rc[T]); L_Rotate(T); } else return; } Maintain(lc[T], false); Maintain(rc[T], true); Maintain(T, false); Maintain(T, true);}inline int Select(int &T, int k){ if (k == sz[lc[T]] + 1) return key[T]; if (k <= sz[lc[T]]) return Select(lc[T], k); else return Select(rc[T], k - sz[lc[T]] - 1);}inline int Del(int &T, int v){ --sz[T]; if (key[T] == v || v < key[T] && !lc[T] || v > key[T] && !rc[T]) { int tmp = key[T]; if (!lc[T] || !rc[T]) T = lc[T] + rc[T]; else key[T] = Del(lc[T], key[T] + 1); // return tmp; } if (v < key[T]) return Del(lc[T], v); else return Del(rc[T], v);}inline void insert(int &T, int v){ if (!T) { key[T = ++tot] = v; sz[T] = 1; return; } ++sz[T]; if (v < key[T]) insert(lc[T], v); else insert(rc[T], v); Maintain(T, v >= key[T]);}void readdata(){ scanf("%d", &n); for (int i = 1; i < n + 1; ++i) { scanf("%d", c + i); insert(T, c[i]); }}void work(){ scanf("%d", &m); for (; m; --m) { int x, delta; switch (getchar(), getchar()) { case 'A': scanf("%d%d", &x, &delta); Del(T, c[x]); c[x] -= delta; if (c[x] > 0) insert(T, c[x]); break; case 'C': scanf("%d%d", &x, &delta); Del(T, c[x]); c[x] += delta; insert(T, c[x]); break; case 'Q': scanf("%d", &x); if (x > sz[T]) printf("-1\n"); else printf("%d\n", Select(T, sz[T] - x + 1)); break; } } printf("%d", sz[T]);}int main(){ init_file(); readdata(); work(); exit(0);}
- 【平衡二叉树】魔兽争霸
- ☆【平衡二叉树】魔兽争霸
- 平衡二叉树平衡法则
- 二叉树--二叉平衡树
- 平衡二叉树的
- 平衡二叉树
- 平衡二叉树
- 平衡二叉树
- 平衡二叉树
- 平衡二叉查找树
- 平衡二叉树 详解
- 平衡二叉树
- 平衡二叉树
- AVL 平衡二叉树
- 平衡二叉树
- 平衡二叉树-红黑树
- 平衡二叉树
- 平衡二叉树
- Android实战技巧之二:组合控件
- 窗口间传递数据
- 万年历代码
- Android学习笔记(19)————实现一个记住密码的Android登陆界面
- iOS开发_iphone 触屏指触行为大全_iphone 有哪些触控事件
- 【平衡二叉树】魔兽争霸
- hdoj 3666 THE MATRIX PROBLEM
- mac os终端颜色显示及vi配置
- autosys 查看job状态
- 马士兵_JAVA自学之路
- 【android中级】之android 背景圆角和图片圆角
- [python在Linux的安装]
- 编程开发人员最具有影响力的十一本书籍 .
- 模拟鼠标移动