BZOJ 4003 / Luogu P3261 [JLOI2015]城池攻占 (左偏树)
左偏树裸题,在树上合并儿子传上来的堆,然后小于当前结点防御值的就pop掉,pop的时候统计答案.
修改的话就像平衡树一样打懒标记就行了.
具体见代码
CODE
#include<bits/stdc++.h>
using namespace std;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
char ch; int flg = 1; for(;!isdigit(ch=getchar());)if(ch=='-')flg=-flg;
for(res=ch-'0';isdigit(ch=getchar());res=res*10+ch-'0'); res*=flg;
}
typedef long long LL;
const int MAXN = 300005;
const int MAXM = 300005;
#define lc t[x].ls
#define rc t[x].rs
struct node {
int ls, rs, d;
LL v, add_tag, mul_tag;
}t[MAXN];
int n, m, cnt, ans1[MAXN], ans2[MAXM];
int dep[MAXN], fir[MAXN], fa[MAXN], c[MAXM];
LL v[MAXN], a[MAXN], h[MAXN];
struct edge { int to, nxt; }e[MAXN];
inline void add(int u, int v) { e[++cnt] = (edge) { v, fir[u] }, fir[u] = cnt; }
vector<int> here[MAXN];
inline void upd(int x) {
if(t[lc].d < t[rc].d) swap(lc, rc);
t[x].d = t[rc].d + 1;
}
inline void mt(int x) {
if(t[x].mul_tag != 1) { //题目中满足只会乘正数,所以能够用堆维护
if(lc)
t[lc].mul_tag *= t[x].mul_tag,
t[lc].add_tag *= t[x].mul_tag,
t[lc].v *= t[x].mul_tag;
if(rc)
t[rc].mul_tag *= t[x].mul_tag,
t[rc].add_tag *= t[x].mul_tag,
t[rc].v *= t[x].mul_tag;
t[x].mul_tag = 1;
}
if(t[x].add_tag) {
if(lc)
t[lc].add_tag += t[x].add_tag,
t[lc].v += t[x].add_tag;
if(rc)
t[rc].add_tag += t[x].add_tag,
t[rc].v += t[x].add_tag;
t[x].add_tag = 0;
}
}
int merge(int x, int y){
if(!x || !y) return x + y;
mt(x), mt(y);
if(t[x].v > t[y].v) swap(x, y);
t[x].rs = merge(t[x].rs, y);
upd(x);
return x;
}
int pop(int x) { mt(x);
int l = t[x].ls, r = t[x].rs;
t[x].ls = t[x].rs = t[x].add_tag = 0; t[x].mul_tag = 1;
return merge(l, r);
}
int dfs(int x) {
int rt = 0;
while(!here[x].empty())
rt = merge(rt, here[x].back()), here[x].pop_back();
for(int i = fir[x]; i; i = e[i].nxt)
dep[e[i].to] = dep[x] + 1, rt = merge(rt, dfs(e[i].to));
while(rt && t[rt].v < h[x])
++ans1[x], ans2[rt] = dep[c[rt]]-dep[x], rt = pop(rt);
if(rt && x > 1) {
if(a[x] == 0) t[rt].v += v[x], t[rt].add_tag += v[x];
else t[rt].v *= v[x], t[rt].add_tag *= v[x], t[rt].mul_tag *= v[x];
}
return rt;
}
int main() {
read(n), read(m); t[0].d = -1;
for(int i = 1; i <= n; ++i) read(h[i]);
for(int i = 2; i <= n; ++i) read(fa[i]), read(a[i]), read(v[i]), add(fa[i], i);
for(int i = 1; i <= m; ++i) read(t[i].v), read(c[i]), here[c[i]].push_back(i), t[i].mul_tag = 1;
int root = dfs(1);
while(root) ans2[root] = dep[c[root]] + 1, root = pop(root); //不要忘了有打通关了的骑士
for(int i = 1; i <= n; ++i) printf("%d\n", ans1[i]);
for(int i = 1; i <= m; ++i) printf("%d\n", ans2[i]);
}
BZOJ 4003 / Luogu P3261 [JLOI2015]城池攻占 (左偏树)的更多相关文章
- [洛谷P3261] [JLOI2015]城池攻占(左偏树)
不得不说,这道题目是真的难,真不愧它的“省选/NOI-”的紫色大火题!!! 花了我晚自习前半节课看题解,写代码,又花了我半节晚自习调代码,真的心态爆炸.基本上改得和题解完全一样了我才过了这道题!真的烦 ...
- BZOJ 4003: [JLOI2015]城池攻占 左偏树 可并堆
https://www.lydsy.com/JudgeOnline/problem.php?id=4003 感觉就是……普通的堆啊(暴论),因为这个堆是通过递归往右堆里加一个新堆或者新节点的,所以要始 ...
- [JLOI2015]城池攻占 左偏树
题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi &l ...
- [luogu3261 JLOI2015] 城池攻占 (左偏树+标记)
传送门 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的 ...
- bzoj 4003 [JLOI2015]城池攻占 —— 左偏树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4003 其实蛮简单的,首先一个城市只会被其子树中的骑士经过,启发我们 dfs 序用可并堆合并子 ...
- BZOJ4003 [JLOI2015]城池攻占 左偏树 可并堆
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4003 题意概括 题意有点复杂,直接放原题了. 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑 ...
- [BZOJ4003][JLOI2015]城池攻占(左偏树)
这题有多种做法,一种是倍增预处理出每个点往上走2^i步最少需要的初始战斗力,一种是裸的启发式合并带标记splay. 每个点合并能攻占其儿子的所有骑士,删去所有无法攻占这个城市的骑士并记录答案. 注意到 ...
- bzoj 4003: 城池攻占 左偏树
题目大意 http://www.lydsy.com/JudgeOnline/problem.php?id=4003 题解 一开始看漏条件了 题目保证当占领城池可以使攻击力乘上\(v_i\)时,一定有\ ...
- P3261 [JLOI2015]城池攻占 (左偏树+标记下传)
左偏树还是满足堆的性质,节点距离就是离最近的外节点(无左或者右儿子 或者二者都没有)的距离,左偏性质就是一个节点左儿子的距离不小于右儿子,由此得:节点距离等于右儿子的距离+1. 本题就是对于每个节点 ...
随机推荐
- Shell脚本中计算字符串长度的5种方法
有时在Linux操作系统中需要计算某个字符串的长度,通过查询资料整理了下目前Shell中获取字符串的长度的多种方法,在这里分享给大家,方法如下: 方法1: 使用wc -L命令wc -L可以获取到当前行 ...
- php栈的定义和出栈、入栈的实现
栈是线性表的一种,他的特点是后入先出,可以这么理解,栈就像一个存东西的盒子,先放进去的在最底层,后放进去的在上层,因为上层的东西把底层的东西压住了,下层的想要出去就必须把上层的先拿开才行. 定义:栈是 ...
- php修改替换数据库图片(文件)
<?php extract($_POST); $date = date('Y-m-d'); $file_name = $_FILES['image']['name'];//获取缓存区图片,格式不 ...
- Boot-crm管理系统开发教程(总结)
这个Boot-crm管理系统我花了大概两周写完,因为是刚学完SSM框架,所以立马开始了这个项目,项目初期,运行书本上给的前端代码都报了许多错误,导致这个原因是因为书本给的 设计说明文档 没有看清楚.然 ...
- Codeforces 1240C. Paint the Tree
传送门 首先每个点 $u$ 只能选择不超过 $k$ 个相连的边 并且设边为 $(u,v)$ ,那么此时 $v$ 也必须选择这条边 因为图是一颗树,显然考虑一下树形 $dp$ 设 $f[x][0/1]$ ...
- centos 服务器 发开防火墙端口
一.概述 在服务器上手动安装了某个软件,需要通过外部访问该软件(有对外开放端口),但是此时访问不通,此时检查,发现是该端口没有在防火墙开放,因此外界访问不了该服务器上的该软件对外提供的功能,基于此,需 ...
- C++入门基础知识(二)
一:引用 概念:是给一个已经存在的变量取一个别名,编译器不会为引用变量开辟内存空间,它和引用的变量公用一块内存空间. 例如: 类型& 引用变量名(对象名)= 引用实体 int& a = ...
- Comparable内部比较器 和 Comparator外部比较器
1:Comparable a:基本数据类型封装类都继承了Comparable接口 b:TreeSet 和TreeMap集合默认是按照自然顺序排序的 c:继承类中实现compareTo()方法,在类内部 ...
- git 查看当前仓库地址以及设置新的仓库地址
1.查看当前仓库地址 git remote show origin 2.设置新的仓库地址 1.先登录 gitlab 查看当前仓库地址: 执行修改地址命令 git remote set-url orig ...
- 谷歌浏览器禁用JS步骤
前奏: 当你想访问一个页面,因为不符合访问条件,而被JS阻拦:或者你打开的页面特效太多,干扰视线:亦或者JS的某个功能禁止了你的某些行为: 是不是很难受, 好办,咱给他禁了不就好啦,大胆地屏蔽它,不管 ...