Luogu 3261 [JLOI2015]城池攻占
BZOJ 4003
需要实现一个可并堆。
每个点维护一个小根堆,然后一开始把所有骑士加入到它所在的点的小根堆当中,实际上空间是$O(m)$的,然后我们从上到下不断合并这个小根堆,合并完之后如果遇到堆顶小于当前城市的防御值就弹掉堆顶顺便记录答案。
对于那些攻占掉城池对骑士的贡献的处理,可以采用打标记的方式实现,在合并的时候$down$一下就好了。注意$down$要写在$merge$函数的最上面,因为有一些点还没有下传标记就被$merge$掉了。
要注意弹出堆顶元素之前要先$down$一下 。
最后在清空一下第一个堆中的元素就好了。
不会算时间复杂度$QωQ$。
Code:
// luogu-judger-enable-o2
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll; const int N = 3e5 + ; int n, m, tot = , head[N], type[N], dep[N], ans[N];
ll def[N], rat[N]; struct Knight {
int pos, ed;
ll atk;
} a[N]; struct Edge {
int to, nxt;
} e[N << ]; inline void add(int from, int to) {
e[++tot].to = to;
e[tot].nxt = head[from];
head[from] = tot;
} template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} template <typename T>
inline void swap(T &x, T &y) {
T t = x; x = y; y = t;
} namespace LeftlistTree {
struct Node {
int lc, rc, dis, id;
ll key, mulTag, addTag;
} s[N]; #define lc(p) s[p].lc
#define rc(p) s[p].rc
#define key(p) s[p].key
#define mulTag(p) s[p].mulTag
#define addTag(p) s[p].addTag
#define dis(p) s[p].dis
#define id(p) s[p].id int root[N], nodeCnt = ; inline int newNode(int p) {
++nodeCnt;
lc(nodeCnt) = rc(nodeCnt) = ;
dis(nodeCnt) = ;
id(nodeCnt) = p;
key(nodeCnt) = a[p].atk;
addTag(nodeCnt) = 0LL, mulTag(nodeCnt) = 1LL;
return nodeCnt;
} inline void down(int p) {
if(!p) return;
if(mulTag(p) != ) {
if(lc(p)) {
key(lc(p)) *= mulTag(p);
addTag(lc(p)) *= mulTag(p);
mulTag(lc(p)) *= mulTag(p);
} if(rc(p)) {
key(rc(p)) *= mulTag(p);
addTag(rc(p)) *= mulTag(p);
mulTag(rc(p)) *= mulTag(p);
} mulTag(p) = ;
} if(addTag(p) != ) {
if(lc(p)) {
key(lc(p)) += addTag(p);
addTag(lc(p)) += addTag(p);
} if(rc(p)) {
key(rc(p)) += addTag(p);
addTag(rc(p)) += addTag(p);
} addTag(p) = ;
}
} int merge(int x, int y) {
down(x), down(y);
if(!x || !y) return x + y;
if(key(x) > key(y)) swap(x, y);
rc(x) = merge(rc(x), y); if(dis(lc(x)) < dis(rc(x))) swap(lc(x), rc(x));
dis(x) = dis(rc(x)) + ;
return x;
} } using namespace LeftlistTree; void solve(int x, int fat, int depth) {
dep[x] = depth;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
solve(y, x, depth + ); root[x] = merge(root[x], root[y]);
} for(; root[x] && key(root[x]) < def[x]; ) {
++ans[x];
a[id(root[x])].ed = x;
down(root[x]);
root[x] = merge(lc(root[x]), rc(root[x]));
} if(root[x]) {
if(!type[x]) {
key(root[x]) += rat[x];
addTag(root[x]) += rat[x];
} else {
key(root[x]) *= rat[x];
mulTag(root[x]) *= rat[x];
addTag(root[x]) *= rat[x];
}
}
} int main() {
// freopen("3.in", "r", stdin);
// freopen("my.out", "w", stdout); read(n), read(m);
for(int i = ; i <= n; i++) read(def[i]);
for(int fat, i = ; i <= n; i++) {
read(fat);
add(fat, i), add(i, fat);
read(type[i]), read(rat[i]);
}
for(int i = ; i <= m; i++) {
read(a[i].atk), read(a[i].pos);
root[a[i].pos] = merge(root[a[i].pos], newNode(i));
} solve(, , ); for(int i = ; i <= n; i++)
printf("%d\n", ans[i]); for(; root[]; ) {
a[id(root[])].ed = ;
down(root[]);
root[] = merge(lc(root[]), rc(root[]));
} for(int i = ; i <= m; i++)
printf("%d\n", dep[a[i].pos] - dep[a[i].ed]); return ;
}
Luogu 3261 [JLOI2015]城池攻占的更多相关文章
- BZOJ 4003 / Luogu P3261 [JLOI2015]城池攻占 (左偏树)
左偏树裸题,在树上合并儿子传上来的堆,然后小于当前结点防御值的就pop掉,pop的时候统计答案. 修改的话就像平衡树一样打懒标记就行了. 具体见代码 CODE #include<bits/std ...
- BZOJ_4003_[JLOI2015]城池攻占_可并堆
BZOJ_4003_[JLOI2015]城池攻占_可并堆 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 ...
- 【BZOJ4003】[JLOI2015]城池攻占 可并堆
[BZOJ4003][JLOI2015]城池攻占 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号 ...
- [bzoj4003][JLOI2015]城池攻占_左偏树
城池攻占 bzoj-4003 JLOI-2015 题目大意:一颗n个节点的有根数,m个有初始战斗力的骑士都站在节点上.每一个节点有一个standard,如果这个骑士的战斗力超过了这个门槛,他就会根据城 ...
- [洛谷P3261] [JLOI2015]城池攻占(左偏树)
不得不说,这道题目是真的难,真不愧它的“省选/NOI-”的紫色大火题!!! 花了我晚自习前半节课看题解,写代码,又花了我半节晚自习调代码,真的心态爆炸.基本上改得和题解完全一样了我才过了这道题!真的烦 ...
- BZOJ4003:[JLOI2015]城池攻占——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4003 https://www.luogu.org/problemnew/show/P3261 小铭 ...
- [JLOI2015]城池攻占
题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi &l ...
- [JLOI2015]城池攻占 左偏树
题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi &l ...
- BZOJ4003[JLOI2015]城池攻占——可并堆
题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖, 其中 fi ...
随机推荐
- iOS设置translucent 引发的坐标问题
iOS NavigationBar + 导航栏 tablevie时候的布局情况,之前迷惑了我很久,怎么也没法理解透明度会影响布局. 接下来看一下以下三种情况的运行结果 1.全部系统默认情况下利用m ...
- thunderbird 设置 邮件回复时内容在上方显示
1 . 编辑->属性 2.选择当前账户,在弹出窗体的右下角 选择 管理标示 ,在弹出窗中选择编辑 3.在弹出标识设置窗体中选择 编写&地址簿 选项卡选择 在引用内容之前回复
- C++输入流和输出流、缓冲区
一.C++输入流和输出流 输入和输出的概念是相对程序而言的. 键盘输入数据到程序叫标准输入,程序数据输出到显示器叫标准输出,标准输入和标准输出统称为标准I/O,文件的输入和输出叫文件I/O. cout ...
- 一个kafka异常
卡夫卡经常超时,而且超时时间固定为三分钟,因为时间长度固定,所以逆推一下,发现现有的配置里面有个session的timeout是三分钟,但是其实后来验证发现真是的原因是connect timeout, ...
- Swift app中的Crash捕获与处理
1. 为什么会Crash 常见的Crash原因有:访问已经被释放的内存,数组越界,使用!解包值为nil的变量.当遇到这些情况时,说明应用已经遇到了很严重的非预期错误,无法再继续运行.操作系统检测到这些 ...
- 微信小程序,请求php后台返回json数据多出隐藏字符问题
这几天在做一个微信小程序注册登录页面的时候碰到一个问题,就是使用wx.request api的时候success中返回的JSON数据前面会多出空白字符,后面网上查了一下是说php bom头问题(详细介 ...
- 杂项-EMS:目录
ylbtech-杂项-EMS:目录 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 7.返回顶部 8.返回顶部 9.返回顶部 ...
- AngularJS:表格
ylbtech-AngularJS:表格 1.返回顶部 1. AngularJS 表格 ng-repeat 指令可以完美的显示表格. 在表格中显示数据 使用 angular 显示表格是非常简单的: A ...
- 注册驱动时如何调用probe函数 ?
platform_driver_register driver_register bus_add_driver //把驱动放入总线的驱动链表里 ...
- 简单的HTTP服务实现
最近因工作需要为外部公司提供http服务,由于内容比较少,同时为了方便安装,就想着自己写一个简单的服务器. 思路是将一个Http服务器嵌入一个Windows Service程序中,于是在网上找了很多资 ...