Description

小铭铭最近获得了一副新的桌游,游戏中需要用 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。注意每个骑士是单独计算的。也就是说一个骑士攻击一座城池,不管结果如何,均不会影响其他骑士攻击这座城

的结果。

现在的问题是,对于每个城池,输出有多少个骑士在这里牺牲;对于每个骑士,输出他攻占的城池数量。

Input

第 1 行包含两个正整数 n;m,表示城池的数量和骑士的数量。

第 2 行包含 n 个整数,其中第 i 个数为 hi,表示城池 i 的防御值。

第 3 到 n +1 行,每行包含三个整数。其中第 i +1 行的三个数为 fi;ai;vi,分别表示管辖

这座城池的城池编号和两个战斗力变化参数。

第 n +2 到 n + m +1 行,每行包含两个整数。其中第 n + i 行的两个数为 si;ci,分别表

示初始战斗力和第一个攻击的城池。

Output

输出 n + m 行,每行包含一个非负整数。其中前 n 行分别表示在城池 1 到 n 牺牲的骑士

数量,后 m 行分别表示骑士 1 到 m 攻占的城池数量。

Sample Input

5 5
50 20 10 10 30
1 1 2
2 0 5
2 0 -10
1 0 10
20 2
10 3
40 4
20 4
35 5

Sample Output

2
2
0
0
0
1
1
3
1
1

HINT

对于 100% 的数据,1 <= n;m <= 300000;
1 <= fi<i; 1 <= ci <= n; -10^18 <= hi,vi,si <=
10^18;ai等于1或者2;当 ai =1 时,vi > 0;保证任何时候骑士战斗力值的绝对值不超过 10^18。

首先我们在每个节点死的是一段子树内的点经各种变化后得到的最小值,为了维护这个过程,我们考虑堆

然后我们发现乘法没有负数,因此两个点同时向上走以后之间的大小关系就不会改变了

因此我们直接在左偏树上打标记即可

代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls ch[x][0]
#define rs ch[x][1]
#define int long long
#define M 300010
using namespace std;
int read()
{
char ch=getchar();int x=,f=;
while(ch>''||ch<'') {if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x*f;
}
int n,m,num;
int head[M],rt[M],a[M],v[M],dis[M],val[M],tag1[M],tag2[M],ch[M][];
int fa[M],deep[M],kill[M],dead[M],c[M],h[M];
struct point{int to,next;}e[M<<];
void add(int from,int to)
{
e[++num].next=head[from];
e[num].to=to;
head[from]=num;
}
void pushdown(int x,int t1,int t2)
{
val[x]*=t1,val[x]+=t2;
tag1[x]*=t1;tag2[x]*=t1,tag2[x]+=t2;
}
void push(int x)
{
pushdown(ls,tag1[x],tag2[x]);
pushdown(rs,tag1[x],tag2[x]);
tag1[x]=,tag2[x]=;
}
int merge(int x,int y)
{
if(!x||!y) return x+y;
push(x),push(y);
if(val[x]>val[y]) swap(x,y);
ch[x][]=merge(rs,y);
if(dis[ls]<dis[rs]) swap(ls,rs);
dis[x]=dis[rs]+;
return x;
}
void dfs(int x)
{
deep[x]=deep[fa[x]]+;
for(int i=head[x];i;i=e[i].next)
{
int to=e[i].to;dfs(to);
rt[x]=merge(rt[x],rt[to]);
}
while(rt[x]&&val[rt[x]]<h[x])
{
push(rt[x]);
dead[x]++;
kill[rt[x]]=deep[c[rt[x]]]-deep[x];
rt[x]=merge(ch[rt[x]][],ch[rt[x]][]);
}
if(a[x]) pushdown(rt[x],v[x],);
else pushdown(rt[x],,v[x]);
}
#undef int
int main()
{
#define int long long
n=read();m=read();
for(int i=;i<=n;i++) h[i]=read();
for(int i=;i<=n;i++)
{
fa[i]=read(),a[i]=read();
v[i]=read(),add(fa[i],i);
}
for(int i=;i<=m;i++)
{
val[i]=read(),c[i]=read();
tag1[i]=,tag2[i]=;
rt[c[i]]=merge(rt[c[i]],i);
}
dfs();
while(rt[])//如果一直没死
{
push(rt[]);
kill[rt[]]=deep[c[rt[]]];
rt[]=merge(ch[rt[]][],ch[rt[]][]);
}
for(int i=;i<=n;i++) printf("%lld\n",dead[i]);
for(int i=;i<=m;i++) printf("%lld\n",kill[i]);
return ;
}

[BZOJ4003]城池攻占的更多相关文章

  1. bzoj-4003 城池攻占

    题意: 给出一个n个结点的有根树,和m个骑士: 树上的结点--城池有一个防御值,骑士有一个战斗力: 当骑士的战斗力大于等于城池时,城池被攻破.骑士的战斗力变化,并向树上的父节点前进: 否则骑士死亡. ...

  2. 【BZOJ4003】[JLOI2015]城池攻占 可并堆

    [BZOJ4003][JLOI2015]城池攻占 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号 ...

  3. [bzoj4003][JLOI2015]城池攻占_左偏树

    城池攻占 bzoj-4003 JLOI-2015 题目大意:一颗n个节点的有根数,m个有初始战斗力的骑士都站在节点上.每一个节点有一个standard,如果这个骑士的战斗力超过了这个门槛,他就会根据城 ...

  4. 【BZOJ】【4003】【JLOI2015】城池攻占

    可并堆 QAQ改了一下午……最终弃疗求助zyf……居然被秒了QAQ真是弱到不行(zyf太神了Orz) 还是先考虑部分分的做法: 1.$n,m\leq 3000$:可以暴力模拟每个骑士的攻打过程,也可以 ...

  5. BZOJ_4003_[JLOI2015]城池攻占_可并堆

    BZOJ_4003_[JLOI2015]城池攻占_可并堆 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 ...

  6. 「JLOI2015」城池攻占 解题报告

    「JLOI2015」城池攻占 注意到任意两个人的战斗力相对大小的不变的 可以离线的把所有人赛到初始点的堆里 然后做启发式合并就可以了 Code: #include <cstdio> #in ...

  7. [洛谷P3261] [JLOI2015]城池攻占(左偏树)

    不得不说,这道题目是真的难,真不愧它的“省选/NOI-”的紫色大火题!!! 花了我晚自习前半节课看题解,写代码,又花了我半节晚自习调代码,真的心态爆炸.基本上改得和题解完全一样了我才过了这道题!真的烦 ...

  8. BZOJ4003 [JLOI2015]城池攻占 左偏树 可并堆

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4003 题意概括 题意有点复杂,直接放原题了. 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑 ...

  9. 【BZOJ4003】【JLOI2015】城池攻占(左偏树)

    题面 题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi ...

随机推荐

  1. 解决SecureCRT连接linux终端中文显示乱码

    现象如下: 原因: SecureCRT的字符集编码不是Linux的默认编码:UTF-8 解决办法: 1.在“选项”找到“会话选项” 2.选择“外观”,设置字符编码为“UTF-8” 3.确定后,继续在终 ...

  2. kibana5.6源码分析2

    1.启动shell脚本:/bin/kibana;   js脚本:/src/cli/cli.js; 2.服务端入口:/src/server/kbn_server.js.使用的web框架为hapi.js. ...

  3. 20165330 2017-2018-2 《Java程序设计》第1周学习总结

    教材学习内容总结 java的历史,地位,特点. java的平台介绍 java应用程序的开发及源文件的编写规则 java反编译特点 安装JDK Windows上 在安装JDK后设置系统环境变量,因为我的 ...

  4. 清除webkit浏览器css设置滚动条

    主要有下面7个属性 ::-webkit-scrollbar 滚动条整体部分,可以设置宽度啥的 ::-webkit-scrollbar-button 滚动条两端的按钮 ::-webkit-scrollb ...

  5. 针对Quant的Python快速入门指南

    作者:用Python的交易员 (原创文章,转载请注明出处) 最近有越来越多的朋友在知乎或者QQ上问我如何学习入门Python,就目前需求来看,我需要写这么一篇指南. 针对整个vn.py框架的学习,整体 ...

  6. CF#301 C:Ice Cave(简单BFS)

    C:Ice Cave 有一个m*n的地图,里面包含'.'表示完整的冰块,'X'表示有裂痕的冰块,当游戏者到达完整的冰块时,这个位置的冰块会变成有裂痕的冰块,如果到达有裂痕的冰块时,游戏者会进入下一关 ...

  7. Python并行编程(五):线程同步之信号量

    1.基本概念 信号量是由操作系统管理的一种抽象数据类型,用于在多线程中同步对共享资源的使用.本质上说,信号量是一个内部数据,用于标明当前的共享资源可以有多少并发读取. 同样在threading中,信号 ...

  8. Using virtual lists

    Download demo project - 15.7 Kb Contents Introduction Virtual list Creating a virtual list Add items ...

  9. 深入了解跟踪(trace)

    深入了解跟踪(trace) 转自:https://www.cnblogs.com/zhijianliutang/p/4113911.html 前言 一提到跟踪俩字,很多人想到警匪片中的场景,同样在我们 ...

  10. abap 中modify 的使用

    1.modify table itab from wa Transporting f1 f2 ... 表示表itab中符合工作区wa 中关键字的一条数据的 f1 f2字段会被wa中对应的字段值更新. ...