传送门

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或者0;

当 ai =1 时,vi > 0;保证任何时候骑士战斗力值的绝对值不超过 10^18。

Solution

把每个骑士视为一个点,给每个城市建左偏树维护战斗力小的在上比较这个值和城市生命值

每个城市做之前先把所有子树合并

需要模仿线段树一样打标记(不打标记20分)

Code

//By Menteur_Hxy
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;
typedef long long LL; LL read() {
LL x=0,f=1; char c=getchar();
while(!isdigit(c)) {if(c=='-')f=-f; c=getchar();}
while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
return x*f;
} const int N=300010;
bool fla[N];
int n,m;
int rt[N],fa[N],nd[N][2],dep[N],bl[N];
LL de[N],wi[N],po[N],laz[N],dis[N],mul[N],add[N],ans1[N],ans2[N];
vector <int> V[N]; void upd(int x,LL mu,LL ad) {
if(!x) return ;
po[x]*=mu,po[x]+=ad;
mul[x]*=mu;add[x]*=mu;add[x]+=ad;
} #define ls nd[x][0]
#define rs nd[x][1]
void pushdown(int x) {
upd(ls,mul[x],add[x]);
upd(rs,mul[x],add[x]);
mul[x]=1,add[x]=0;
} int merge(int x,int y) {
if(!x||!y) return x+y;
pushdown(x),pushdown(y);
if(po[x]>po[y]||(po[x]==po[y]&&x>y)) swap(x,y);
fa[rs=merge(rs,y)]=x;
if(dis[ls]<dis[rs]) swap(ls,rs);
dis[x]=dis[rs]+1;
return x;
} void dfs(int u) {
int siz=V[u].size();
F(i,0,siz-1) { int v=V[u][i];
dep[v]=dep[u]+1;
dfs(v);
if(rt[u]&&rt[v]) rt[u]=merge(rt[u],rt[v]);
else rt[u]=rt[v]+rt[u];
}
while(rt[u]&&po[rt[u]]<de[u]) {
pushdown(rt[u]);po[rt[u]]=-1;
ans2[rt[u]]=dep[bl[rt[u]]]-dep[u];
rt[u]=merge(nd[rt[u]][0],nd[rt[u]][1]);
ans1[u]++;
}
if(fla[u]) upd(rt[u],wi[u],0);
else upd(rt[u],1,wi[u]);
} int main() {
// freopen("rand.txt","r",stdin);
// freopen("2.txt","w",stdout);
n=read(),m=read();
F(i,1,n) de[i]=read();
F(i,1,n-1) {
int father=read();
V[father].push_back(i+1);
fla[i+1]=read(); wi[i+1]=read();
}
F(i,1,m) {
po[i]=read();
bl[i]=read();mul[i]=1;
rt[bl[i]]=merge(rt[bl[i]],i);
}
dep[1]=1;
dfs(1);
F(i,1,n) printf("%lld\n",ans1[i]);
F(i,1,m) {
if(po[i]!=-1) ans2[i]=dep[bl[i]];
printf("%lld\n",ans2[i]);
}
return 0;
}

[luogu3261 JLOI2015] 城池攻占 (左偏树+标记)的更多相关文章

  1. [JLOI2015]城池攻占 左偏树

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

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

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

  3. BZOJ 4003 / Luogu P3261 [JLOI2015]城池攻占 (左偏树)

    左偏树裸题,在树上合并儿子传上来的堆,然后小于当前结点防御值的就pop掉,pop的时候统计答案. 修改的话就像平衡树一样打懒标记就行了. 具体见代码 CODE #include<bits/std ...

  4. BZOJ 4003: [JLOI2015]城池攻占 左偏树 可并堆

    https://www.lydsy.com/JudgeOnline/problem.php?id=4003 感觉就是……普通的堆啊(暴论),因为这个堆是通过递归往右堆里加一个新堆或者新节点的,所以要始 ...

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

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

  6. [BZOJ4003][JLOI2015]城池攻占(左偏树)

    这题有多种做法,一种是倍增预处理出每个点往上走2^i步最少需要的初始战斗力,一种是裸的启发式合并带标记splay. 每个点合并能攻占其儿子的所有骑士,删去所有无法攻占这个城市的骑士并记录答案. 注意到 ...

  7. bzoj 4003 [JLOI2015]城池攻占 —— 左偏树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4003 其实蛮简单的,首先一个城市只会被其子树中的骑士经过,启发我们 dfs 序用可并堆合并子 ...

  8. bzoj 4003: 城池攻占 左偏树

    题目大意 http://www.lydsy.com/JudgeOnline/problem.php?id=4003 题解 一开始看漏条件了 题目保证当占领城池可以使攻击力乘上\(v_i\)时,一定有\ ...

  9. P3261 [JLOI2015]城池攻占 (左偏树+标记下传)

    左偏树还是满足堆的性质,节点距离就是离最近的外节点(无左或者右儿子  或者二者都没有)的距离,左偏性质就是一个节点左儿子的距离不小于右儿子,由此得:节点距离等于右儿子的距离+1. 本题就是对于每个节点 ...

随机推荐

  1. 【MongoDB】windows平台搭建Mongo数据库复制集(相似集群)(三)

    关于windows平台搭建Mongo数据库复制集这个话题,我已经在前面写了两篇博客 第一篇: 怎样在windows平台搭建Mongo数据库复制集 第二篇: 数据同步和故障自适应測试 在本篇里面,咱们重 ...

  2. C语言 - 头文件使用案例

    源代码分门别类管理,通过头文件. 放置一些函数声明,变量声明,常量定义,宏定义. hotel.h #ifndef HOTEL_H_INCLUDED #define HOTEL_H_INCLUDED # ...

  3. B1965 [Ahoi2005]SHUFFLE 洗牌 数论

    这个题的规律很好找,就是奇数直接除二,偶数除二加n/2.把这个规律整理一下就是(x * 2) % (n + 1),然后就直接求逆元就行了.一直30分的原因是qpow函数传参的时候用的int,然而变量是 ...

  4. BZOJ-4706 B君的多边形 OEIS

    题面 题意:有一个正n多边形,我们要连接一些对角线,把这个多边形分成若干个区域,要求连接的对角线不能相交,每个点可以连出也可以不连出对角线,即最终不要求所有区域均为三角形,问总方案数mod (10^9 ...

  5. Liunx搜索命令行

    1.grep grep(General Regular Expression Parser,通用规则表达式分析程序)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来. 它的使 ...

  6. BZOJ 3060 Kruskal

    思路: 把from&to都>k的直接加边 剩下的如果是一棵树就加. 否则ans++ (我的代码写的是反着的 不过意思都一样) //By SiriusRen #include <cs ...

  7. POJ 3258 (NOIP2015 D2T1跳石头)

    河中跳房子 总时间限制: 1000ms 内存限制: 65536kB 描述 每年奶牛们都要举办各种特殊版本的跳房子比赛,包括在河里从一个岩石跳到另一个岩石.这项激动人心的活动在一条长长的笔直河道中进行, ...

  8. springmvc-servlet.xml 第二种选择

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  9. VirtualBox里如何正确安装增强工具(图文详解)

    不多说,直接上干货! 找到 复制到

  10. Service不完全解析

    本篇的内容并不是介绍service使用方法和生命周期的,而是对其中的一些要点进行记录和分析. 我们都知道,Service是一个在后台执行的应用组件,用于在后台进行长期操作,例如进行网络事务,播放背景音 ...