博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Luogu 3261 [JLOI2015]城池攻占
阅读量:4330 次
发布时间:2019-06-06

本文共 4317 字,大约阅读时间需要 14 分钟。

BZOJ 4003

需要实现一个可并堆。

每个点维护一个小根堆,然后一开始把所有骑士加入到它所在的点的小根堆当中,实际上空间是$O(m)$的,然后我们从上到下不断合并这个小根堆,合并完之后如果遇到堆顶小于当前城市的防御值就弹掉堆顶顺便记录答案。

对于那些攻占掉城池对骑士的贡献的处理,可以采用打标记的方式实现,在合并的时候$down$一下就好了。注意$down$要写在$merge$函数的最上面,因为有一些点还没有下传标记就被$merge$掉了。

要注意弹出堆顶元素之前要先$down$一下 。

最后在清空一下第一个堆中的元素就好了。

不会算时间复杂度$QωQ$。

Code:

// luogu-judger-enable-o2#include 
#include
using namespace std;typedef long long ll;const int N = 3e5 + 5;int n, m, tot = 0, 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 << 1];inline void add(int from, int to) { e[++tot].to = to; e[tot].nxt = head[from]; head[from] = tot;}template
inline void read(T &X) { X = 0; char ch = 0; T op = 1; for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') op = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) X = (X << 3) + (X << 1) + ch - 48; X *= op;} template
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 = 0; inline int newNode(int p) { ++nodeCnt; lc(nodeCnt) = rc(nodeCnt) = 0; dis(nodeCnt) = 0; 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) != 1) { 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) = 1; } if(addTag(p) != 0) { 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) = 0; } } 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)) + 1; 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 + 1); 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 = 1; i <= n; i++) read(def[i]); for(int fat, i = 2; i <= n; i++) { read(fat); add(fat, i), add(i, fat); read(type[i]), read(rat[i]); } for(int i = 1; i <= m; i++) { read(a[i].atk), read(a[i].pos); root[a[i].pos] = merge(root[a[i].pos], newNode(i)); } solve(1, 0, 1); for(int i = 1; i <= n; i++) printf("%d\n", ans[i]); for(; root[1]; ) { a[id(root[1])].ed = 0; down(root[1]); root[1] = merge(lc(root[1]), rc(root[1])); } for(int i = 1; i <= m; i++) printf("%d\n", dep[a[i].pos] - dep[a[i].ed]); return 0;}
View Code

 

转载于:https://www.cnblogs.com/CzxingcHen/p/9858714.html

你可能感兴趣的文章
(简单)华为Nova青春 WAS-AL00的USB调试模式在哪里开启的流程
查看>>
图论知识,博客
查看>>
[原创]一篇无关技术的小日记(仅作暂存)
查看>>
20145303刘俊谦 Exp7 网络欺诈技术防范
查看>>
原生和jQuery的ajax用法
查看>>
iOS开发播放文本
查看>>
20145202马超《java》实验5
查看>>
JQuery 事件
查看>>
main(argc,argv[])
查看>>
在线教育工具—白板系统的迭代1——bug监控排查
查看>>
121. Best Time to Buy and Sell Stock
查看>>
hdu 1005 根据递推公式构造矩阵 ( 矩阵快速幂)
查看>>
安装php扩展
查看>>
百度移动搜索主要有如下几类结果构成
查看>>
Python爬虫面试题170道:2019版【1】
查看>>
JavaBean规范
查看>>
第四阶段 15_Linux tomcat安装与配置
查看>>
NAS 创建大文件
查看>>
学习笔记-模块之xml文件处理
查看>>
接口测试用例
查看>>