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. 《C#求职宝典》读书笔记

    王小科 电子工业出版 第一篇 面试求职第一步 一个例子:一支行军中的队伍长100米,一个传令兵从队尾跑至队头,再立即返回队尾,队伍正好前进了100米.假设队伍 和传令兵行进的速度恒定,问传令兵跑了多少 ...

  2. Linux环境安装redis

    redis官网地址:http://www.redis.io/ 最新版本:2.8.3 在Linux下安装Redis非常简单,具体步骤如下(官网有说明): 1.下载源码,解压缩后编译源码. $ wget ...

  3. hadoop之 Zookeeper 分布式应用程序协调服务

    (1) Zookeeper 在 Hadoop 集群中的作用 Zookeeper 是分布式管理协作框架,Zookeeper 集群用来保证 Hadoop 集群的高可用,(高可用的含义是:集群中就算有一部分 ...

  4. php://input解决APP发送图片问题

    今天公司要求用APP发送一个图片到PHP程序接收并保存起来,而且中间还需要很多参数! 以前没有做过APP和PHP交互,这次算是一个挑战吧(对一个没有人指导实习生来说) 1.APP发1.jpg,而且带有 ...

  5. bzoj 5093 [Lydsy1711月赛]图的价值——第二类斯特林数

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5093 不要见到组合数就拆! 枚举每个点的度数,则答案为 \( n*\sum\limits_{ ...

  6. 在laravel中使用QrCode包生成二维码

    http://laravelacademy.org/post/2605.html 一切都是按照文档上的说明操作,没有问题

  7. git 基本操作 https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013744142037508cf42e51debf49668810645e02887691000

    1.创建版本库 (即仓库  repository)简单理解为一个目录,这个目录里的所有文件都可以被git管理起来,每个文件的修改删除,git都能跟踪,一边任何时刻都可以追踪历史,或者在将来某个时刻可以 ...

  8. log4net生成多个日志文件

    使用Log4Net日志组件时,经常会碰到这样一种场景,我想把错误的日志记录在Error.log文件中,而把操作的日志放在Operation.log文件中 经过几番尝试,终于实现了,在此把Log4Net ...

  9. java中绘图-----那个鼠标等的监听我还是不太会,,好苦恼啊。不知道这些监听事件是怎么区分的

    总结::监听到底该怎么用 事件的区分是靠判断还是 package com.a.b; //我想实现,当我点击一个按钮时,这个frame里可以画出实心的矩形 import java.awt.Color; ...

  10. java数字游戏基础篇

    题目: 1.100以内,程序先产生一个随机数,然后用户从控制台输入数字,猜是大了还是小了,第7次时 输出 “您太笨了,答案是”+x 思路:1.随机数,所以用到random 2.用户从键盘输入 ,则用到 ...