BZOJ4003:[JLOI2015]城池攻占——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4003
https://www.luogu.org/problemnew/show/P3261
小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池。这 n 个城池用 1 到 n 的整数表示。除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi <i。也就是说,所有城池构成了一棵有根树。这 m 个骑士用 1 到 m 的整数表示,其中第 i 个骑士的初始战斗力为 si,第一个攻击的城池为 ci。
每个城池有一个防御值 hi,如果一个骑士的战斗力大于等于城池的生命值,那么骑士就可以占领这座城池;否则占领失败,骑士将在这座城池牺牲。占领一个城池以后,骑士的战斗力将发生变化,然后继续攻击管辖这座城池的城池,直到占领 1 号城池,或牺牲为止。
除 1 号城池外,每个城池 i 会给出一个战斗力变化参数 ai;vi。若 ai =0,攻占城池 i 以后骑士战斗力会增加 vi;若 ai =1,攻占城池 i 以后,战斗力会乘以 vi。注意每个骑士是单独计算的。也就是说一个骑士攻击一座城池,不管结果如何,均不会影响其他骑士攻击这座城池的结果。
现在的问题是,对于每个城池,输出有多少个骑士在这里牺牲;对于每个骑士,输出他攻占的城池数量。
讲真,这题出在省选里就是为了卡掉一群不学左偏树的人。
题还真不难,左偏树比较裸的题。
暴力显然是O(nm)的。
但是如果我们对于每次模拟爬树的时候多让一些人跟着一起爬的话就能优化时间。
于是我们从叶子节点开始往根爬,把沿途节点的人合并到一起,维护一下这些人战斗力最小的那个,这样碰到城池打不破的时候弹掉最小的,直到最小的那个能打过了就是剩下的人都能打过了。
(当然说的那么简单你需要至少push两个lazy标记来更新战斗力,所以真恶心。)
分析复杂度(仅供参考因为我不会分析),最坏到最后一个人都没死,合并复杂度O(mlogm),弹出也是O(mlogm),只爬了一次树所以是O(n),于是整体复杂度就是O(mlogm)的了。
(当然这题你需要卡常技巧,洛谷一个点1s我卡了半个小时才过的……)
#include<cstdio>
#include<cmath>
#include<iostream>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
typedef long long ll;
const int N=3e5+;
inline ll read(){
ll x=,w=;char ch=;
while(ch<''||ch>''){if(ch=='-')w=-;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*w;
}
struct node{
int to,nxt;
}e[N];
struct tree{
int l,r,dis;
ll val;
}tr[N];
int head[N],cnt,die[N],knight[N],rt[N];
ll h[N],f[N],a[N],v[N],lazy[N][];
inline void add(int u,int v){
e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
}
inline void init(int x){
lazy[x][]=lazy[x][]=;
lazy[x][]=;
}
inline void push(int x){
if(!x)return;
if(tr[x].l){
tr[tr[x].l].val*=lazy[x][];tr[tr[x].l].val+=lazy[x][];
knight[tr[x].l]+=lazy[x][];
lazy[tr[x].l][]*=lazy[x][];lazy[tr[x].l][]*=lazy[x][];
lazy[tr[x].l][]+=lazy[x][];lazy[tr[x].l][]+=lazy[x][];
}
if(tr[x].r){
tr[tr[x].r].val*=lazy[x][];tr[tr[x].r].val+=lazy[x][];
knight[tr[x].r]+=lazy[x][];
lazy[tr[x].r][]*=lazy[x][];lazy[tr[x].r][]*=lazy[x][];
lazy[tr[x].r][]+=lazy[x][];lazy[tr[x].r][]+=lazy[x][];
}
init(x);
}
int merge(int x,int y){
if(!x||!y)return x+y;
push(x);push(y);
if(tr[x].val>tr[y].val)
swap(x,y);
tr[x].r=merge(tr[x].r,y);
if(tr[tr[x].l].dis<tr[tr[x].r].dis)
swap(tr[x].l,tr[x].r);
tr[x].dis=tr[tr[x].r].dis+;
return x;
}
int del(int x){
push(x);
return merge(tr[x].l,tr[x].r);
}
void dfs(int u){
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f[u])continue;
dfs(v);
rt[u]=merge(rt[u],rt[v]);
}
while(rt[u]&&tr[rt[u]].val<h[u]){
die[u]++;
rt[u]=del(rt[u]);
}
if(rt[u]){
knight[rt[u]]++;
lazy[rt[u]][]++;
if(!a[u]){
tr[rt[u]].val+=v[u];
lazy[rt[u]][]+=v[u];
}
else{
tr[rt[u]].val*=v[u];
lazy[rt[u]][]*=v[u];
lazy[rt[u]][]*=v[u];
}
}
}
void upt(int x){
if(!x)return;
push(x);
upt(tr[x].l);upt(tr[x].r);
}
int main(){
int n=read(),m=read();
for(int i=;i<=n;i++)h[i]=read();
for(int i=;i<=n;i++){
f[i]=read(),a[i]=read(),v[i]=read();
add(f[i],i);
}
for(int i=;i<=m;i++)init(i);
for(int i=;i<=m;i++){
tr[i].val=read();
int c=read();
rt[c]=merge(i,rt[c]);
}
dfs();
upt(rt[]);
for(int i=;i<=n;i++)printf("%d\n",die[i]);
for(int i=;i<=n;i++)printf("%d\n",knight[i]);
return ;
}
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
BZOJ4003:[JLOI2015]城池攻占——题解的更多相关文章
- [bzoj4003][JLOI2015]城池攻占_左偏树
城池攻占 bzoj-4003 JLOI-2015 题目大意:一颗n个节点的有根数,m个有初始战斗力的骑士都站在节点上.每一个节点有一个standard,如果这个骑士的战斗力超过了这个门槛,他就会根据城 ...
- BZOJ4003 [JLOI2015]城池攻占 左偏树 可并堆
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4003 题意概括 题意有点复杂,直接放原题了. 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑 ...
- P3261 [JLOI2015]城池攻占 题解
题目 小铭铭最近获得了一副新的桌游,游戏中需要用 \(m\) 个骑士攻占 \(n\) 个城池.这 \(n\) 个城池用 \(1\) 到 \(n\) 的整数表示.除 \(1\) 号城池外,城池 \(i\ ...
- BZOJ4003[JLOI2015]城池攻占——可并堆
题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖, 其中 fi ...
- [BZOJ4003][JLOI2015]城池攻占(左偏树)
这题有多种做法,一种是倍增预处理出每个点往上走2^i步最少需要的初始战斗力,一种是裸的启发式合并带标记splay. 每个点合并能攻占其儿子的所有骑士,删去所有无法攻占这个城市的骑士并记录答案. 注意到 ...
- BZOJ4003 JLOI2015城池攻占
用左偏树模拟攻占的过程,维护最小值,最多入和出m次,每次log复杂度. #include<bits/stdc++.h> using namespace std; ; typedef lon ...
- BZOJ4003 [JLOI2015]城池攻占
这题有两种做法来着... 第一种就是一开始想到的比较不靠谱,不过貌似可以过掉: 看从$1$号节点开始到$p$号节点最大需要的体力,记录单调上升的体力,询问的时候二分跳着走就可以了 不过精度问题还有可能 ...
- 【BZOJ4003】[JLOI2015]城池攻占 可并堆
[BZOJ4003][JLOI2015]城池攻占 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号 ...
- BZOJ_4003_[JLOI2015]城池攻占_可并堆
BZOJ_4003_[JLOI2015]城池攻占_可并堆 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 ...
随机推荐
- webpack loader 生成虚拟文件的方案
此文已由作者张磊授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 前言 使用 webpack 的时候,难免需要写一些 loader,接着就会遇到一个很纠结的问题.该 loade ...
- nuget在jenkins上不能自动还原项目依赖包---笔记
最近遇到一个情况,IDE 是 VS2015 Update3 ,新建一个library项目(暂时叫做 mytests),然后用 nuget 安装了一个 Shouldly 包 在 VS 上一切正常,可以跑 ...
- 如何往eclipse中导入maven项目
现在公司中大部分项目可能都是使用maven来构建,假如现在摆在你面前有一个maven的项目,如果你要学习它,如何将它导入到像eclipse这样的集成开发工具中呢,以项目public_class_1为例 ...
- word record 4
word record 4 pledge p le g vt. 保证,许诺 snowflake falke->n. 小薄片:火花 deputy de piu ti n. 代理人,代表 etch ...
- lesson 18 Electric currents in modern art
lesson18 Electric currents in modern art electricity n. 电力:电流; electric adj. 电的:电动的; electronic adj. ...
- sqlserver错误126解决方法
是不是很尴尬! 华丽的分割线下便是解决方法: 1.打开sqlserver配置管理器. 2.选择sqlserver网络配置,并禁用VIA协议确定保存. 3.在服务里面启动[SQL Server (SQL ...
- django 增删改查操作 数据库Mysql
下面介绍一下django增删改查操作: 1.view.py # -*- coding: utf-8 -*-from __future__ import unicode_literalsfrom dja ...
- ionic LoadingController 模块使用
html 代码: <ion-header> <ion-navbar> <ion-title>Loading</ion-title> </ion-n ...
- Turtlebot
Turtlebot2 数据分析: imu信息:只有z轴的旋转yaw,没有xy的角速度. odom:利用轮速计,提供平移变换,没有z方向的平移. 好的网站,详细介绍了turtlebot的使用:https ...
- mybatis 枚举类型使用
一.首先定义接口,提供获取数据库存取的值得方法,如下: public interface BaseEnum { int getCode(); } 二.定义mybatis的typeHandler扩展类, ...