[洛谷P3261][JLOI2015]城池攻占
题目大意:有$n$个点的树,第$i$个节点有一个权值$h_i$,$m$个骑士,第$i$个骑士攻击力为$v_i$,一个骑士可以把从它开始的连续的父亲中比它小的节点攻破,攻破一个节点可以把攻击力加或乘一个数(乘的数大于$0$)(每个骑士独立),问每个骑士可以攻破多少个点,每个点会阻挡住多少个骑士。
题解:可以把所有骑士一起考虑,建一个小根堆,存可以攻打到这个点的骑士,每个若堆顶小于该点,就弹出,写一个打标记的可并堆就行了。
卡点:快读中读入$long\;long$的部分返回值变成$int$
C++ Code:
#include <algorithm>
#include <cstdio>
#include <cctype>
namespace __IO {
namespace R {
int x, ch, f;
inline int read() {
ch = getchar(); f = 1;
while (isspace(ch)) ch = getchar();
if (ch == '-') f = -1, ch = getchar();
for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15);
return x * f;
}
long long X;
inline long long readll() {
ch = getchar(); f = 1;
while (isspace(ch)) ch = getchar();
if (ch == '-') f = -1, ch = getchar();
for (X = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) X = X * 10 + (ch & 15);
return X * f;
}
}
}
using __IO::R::read;
using __IO::R::readll; #define maxn 300010 int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxn << 1];
inline void addedge(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
} namespace Heap {
int fa[maxn], lc[maxn], rc[maxn], dis[maxn];
long long M[maxn], A[maxn], V[maxn];
inline void Mul(int rt, long long num) {
if (rt) M[rt] *= num, A[rt] *= num, V[rt] *= num;
}
inline void Add(int rt, long long num) {
if (rt) A[rt] += num, V[rt] += num;
}
inline void pushdown(int rt) {
long long &__M = M[rt], &__A = A[rt];
if (__M != 1) {
Mul(lc[rt], __M);
Mul(rc[rt], __M);
__M = 1;
}
if (__A) {
Add(lc[rt], __A);
Add(rc[rt], __A);
__A = 0;
}
} int __merge(int x, int y) {
if (!x || !y) return x | y;
pushdown(x), pushdown(y);
if (V[x] > V[y]) std::swap(x, y);
rc[x] = __merge(rc[x], y), fa[rc[x]] = x;
if (dis[lc[x]] < dis[rc[x]]) std::swap(lc[x], rc[x]);
dis[x] = dis[rc[x]] + 1;
return x;
}
int merge(int x, int y) {
fa[x] = fa[y] = 0;
return __merge(x, y);
} int insert(int rt, long long val, int pos) {
V[pos] = val, M[pos] = 1, A[pos] = 0;
return merge(rt, pos);
}
int pop(int rt) {
pushdown(rt);
return merge(lc[rt], rc[rt]);
}
} int n, m;
int a[maxn], c[maxn], dead[maxn], num[maxn];
int rt[maxn], dep[maxn];
long long w[maxn], v[maxn];
void dfs(int u) {
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
dep[v] = dep[u] + 1;
dfs(v);
rt[u] = Heap::merge(rt[u], rt[v]);
}
while (rt[u] && Heap::V[rt[u]] < w[u]) {
num[u]++, dead[rt[u]] = u;
rt[u] = Heap::pop(rt[u]);
}
if (rt[u]) {
if (a[u]) Heap::Mul(rt[u], v[u]);
else Heap::Add(rt[u], v[u]);
}
} int main() {
n = read(), m = read();
for (int i = 1; i <= n; i++) w[i] = readll();
for (int i = 2, fa; i <= n; i++) {
fa = read(), a[i] = read(), v[i] = readll();
addedge(fa, i);
}
for (int i = 1; i <= m; i++) {
long long V = readll(); c[i] = read();
rt[c[i]] = Heap::insert(rt[c[i]], V, i);
}
dfs(dep[1] = 1);
for (int i = 1; i <= n; i++) printf("%d\n", num[i]);
for (int i = 1; i <= m; i++) printf("%d\n", dep[c[i]] - dep[dead[i]]);
return 0;
}
[洛谷P3261][JLOI2015]城池攻占的更多相关文章
- [洛谷P3261] [JLOI2015]城池攻占(左偏树)
		
不得不说,这道题目是真的难,真不愧它的“省选/NOI-”的紫色大火题!!! 花了我晚自习前半节课看题解,写代码,又花了我半节晚自习调代码,真的心态爆炸.基本上改得和题解完全一样了我才过了这道题!真的烦 ...
 - 洛谷P3261 [JLOI2015]城池攻占(左偏树)
		
传送门 每一个城市代表的点开一个小根堆,把每一个骑士合并到它开始攻占的城池所代表的点上 然后开始dfs,每一次把子树里那些还活着的骑士合并上来 然后再考虑当前点的堆,一直pop直到骑士全死光或者剩下的 ...
 - P3261 [JLOI2015]城池攻占 题解
		
题目 小铭铭最近获得了一副新的桌游,游戏中需要用 \(m\) 个骑士攻占 \(n\) 个城池.这 \(n\) 个城池用 \(1\) 到 \(n\) 的整数表示.除 \(1\) 号城池外,城池 \(i\ ...
 - P3261 [JLOI2015]城池攻占 (左偏树+标记下传)
		
左偏树还是满足堆的性质,节点距离就是离最近的外节点(无左或者右儿子 或者二者都没有)的距离,左偏性质就是一个节点左儿子的距离不小于右儿子,由此得:节点距离等于右儿子的距离+1. 本题就是对于每个节点 ...
 - P3261 [JLOI2015]城池攻占
		
思路 左偏树维护每个骑士的战斗力和加入的深度(因为只能向上跳) 注意做乘法的时候加法tag会受到影响 代码 #include <cstdio> #include <algorithm ...
 - 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]城池攻占——题解
		
https://www.lydsy.com/JudgeOnline/problem.php?id=4003 https://www.luogu.org/problemnew/show/P3261 小铭 ...
 
随机推荐
- ASP.NET MVC 微信JS-SDK认证
			
layout: post title: ASP.NET MVC 微信JS-SDK认证 category: .net date: 2016-11-01 00:00:00 tags: .net javas ...
 - PostgreSQL 使用总结
			
1. USING的使用 USING是个缩写的概念:它接收一个用逗号分隔的字段名字列表, 这些字段必须是连接表共有的,最终形成一个连接条件,表示这些字段对必须相同. USING (a, b, c) 等效 ...
 - 聊聊WS-Federation(test)
			
本文来自网易云社区 单点登录(Single Sign On),简称为 SSO,目前已经被大家所熟知.简单的说, 就是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. 举例: 我们 ...
 - 第六模块:WEB框架开发 第1章·Django框架开发1~50
			
01-Django基础介绍 02-Web应用程序1 03-Web应用程序2 04-http请求协议1 05-http请求协议2 06-http协议之响应协议 07-wsgire模块1 08-wsgir ...
 - 第三模块:面向对象&网络编程基础 第1章 面向对象
			
我的失败与梦想(一) 我的失败与梦想之为何创办路飞学城 01-编程范式 02-面向过程编程 03-面向对象编程介绍 04-定义类与实例化出对象 05-如何使用类 06-如何使用对象 07-属性查找与绑 ...
 - STL之--插入迭代器(back_inserter,inserter,front_inserter的区别)
			
除了普通迭代器,C++标准模板库还定义了几种特殊的迭代器,分别是插入迭代器.流迭代器.反向迭代器和移动迭代器,定义在<iterator>头文件中,下面主要介绍三种插入迭代器(back_in ...
 - CSP201403-2:窗口
			
引言:CSP(http://www.cspro.org/lead/application/ccf/login.jsp)是由中国计算机学会(CCF)发起的"计算机职业资格认证"考试, ...
 - Python3 Tkinter-Radionbutton
			
1.创建单选按钮 from tkinter import * root=Tk() Radiobutton(root,text='b1').pack() Radiobutton(root,text='b ...
 - 6.hdfs的存储过程
			
1.hdfs 怎么存储 切割存储 2. 为何每块是128m 与io读写速度有关,一般人的接受速度1s中,而磁盘的读写速度为100m/s,在读取文件时候需要硬盘寻找地址,一般读懂速度和寻找之间的比例是1 ...
 - HDU 3007 Buried memory(计算几何の最小圆覆盖,模版题)
			
Problem Description Each person had do something foolish along with his or her growth.But,when he or ...