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]城池攻占的更多相关文章

  1. BZOJ 4003 / Luogu P3261 [JLOI2015]城池攻占 (左偏树)

    左偏树裸题,在树上合并儿子传上来的堆,然后小于当前结点防御值的就pop掉,pop的时候统计答案. 修改的话就像平衡树一样打懒标记就行了. 具体见代码 CODE #include<bits/std ...

  2. BZOJ_4003_[JLOI2015]城池攻占_可并堆

    BZOJ_4003_[JLOI2015]城池攻占_可并堆 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 ...

  3. 【BZOJ4003】[JLOI2015]城池攻占 可并堆

    [BZOJ4003][JLOI2015]城池攻占 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号 ...

  4. [bzoj4003][JLOI2015]城池攻占_左偏树

    城池攻占 bzoj-4003 JLOI-2015 题目大意:一颗n个节点的有根数,m个有初始战斗力的骑士都站在节点上.每一个节点有一个standard,如果这个骑士的战斗力超过了这个门槛,他就会根据城 ...

  5. [洛谷P3261] [JLOI2015]城池攻占(左偏树)

    不得不说,这道题目是真的难,真不愧它的“省选/NOI-”的紫色大火题!!! 花了我晚自习前半节课看题解,写代码,又花了我半节晚自习调代码,真的心态爆炸.基本上改得和题解完全一样了我才过了这道题!真的烦 ...

  6. BZOJ4003:[JLOI2015]城池攻占——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4003 https://www.luogu.org/problemnew/show/P3261 小铭 ...

  7. [JLOI2015]城池攻占

    题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi &l ...

  8. [JLOI2015]城池攻占 左偏树

    题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi &l ...

  9. BZOJ4003[JLOI2015]城池攻占——可并堆

    题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖, 其中 fi ...

随机推荐

  1. 剑指offer-第五章优化时间和空间效率(把数组排列成最小的数)

    题目:输入一个正整数数组,将所有的数,排列起来,组成一个最小的数.

  2. Mac OS X显示隐藏文件命令

    defaults write com.apple.finder AppleShowAllFiles Yes && killall Finder //显示隐藏文件 defaults wr ...

  3. nmon的使用

    Linux性能评测工具之一:nmon篇 分类: 敏捷实践2010-06-08 11:27 7458人阅读 评论(0) 收藏 举报 工具linuxfilesystemsaixx86excel   目录( ...

  4. openfaas 私有镜像配置

    备注: 此项目是使用nodejs  生成唯一id 的\ 预备环境 docker harbor faas-cli openfaas k8s 1. 项目初始化 faas-cli new node --la ...

  5. C# 实现程序只启动一次(实现程序自重启)

    程序运行过程中,不能有多个实例运行,并且需要程序自己可以重启(重新运行),所以代码如果下代码: static void Main() { bool createNew; using (System.T ...

  6. 为什么 FastAdmin 的插件不全部免费?

    为什么 FastAdmin 的插件不全部免费? 主要还是有以下几个原因. 支持开发者. 为了支付网站空间费和 CDN 费. 有收入后可以更好的开发 FastAdmin.

  7. python 无序模块,hashlib模块

    无序模块什么是无序模块,将字符串转化为十六进制的字符串类型,主要运用在网络编程中.1,json模块 1,用于网络传输,跨语言,可用的类型有 int str 列表-->元祖会变为列表 字典--&g ...

  8. Chrome 的审查元素功能有哪些奇技淫巧

    学习地址: https://www.zhihu.com/question/34682699

  9. telnet WIN7设置回显办法

    windows 2000及XP默认是关闭telnet回显的,这样在操作上很不方便,要让Telnet程序实现本地回显可以按如下步骤操作:1.在命令窗口中运行不带任何参数的telnet命令,执行 /hel ...

  10. python's fourteenth day for me 内置函数

    locals:  函数会以字典的类型返回当前位置的全部局部变量. globals:  函数会以字典的了类型返回全部的全局变量. a = def func(): b = print(locals()) ...