传送门

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. 【ACM】hdu_zs3_1005_String Matching_201308100920

    String Matching Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 20000/10000K (Java/Other)Tota ...

  2. HDU多校赛第9场 HDU 4965Fast Matrix Calculation【矩阵运算+数学小知识】

    难度上.,,确实...不算难 问题是有个矩阵运算的优化 题目是说给个N*K的矩阵A给个K*N的矩阵B(1<=N<=1000 && 1=<K<=6),先把他们乘起 ...

  3. ORACLE 树形查询 树查询

    前台树结构依据个人的权限登录变化 全部我查询要依据 树的ID 查询以下全部的子节点 以及本节点的信息 select * from table start with id = #{id} connect ...

  4. js限制checkbox选中个数

    今天在做项目时,碰到一个问题,我须要展示多个checkbox复选框,而仅仅能同意最多选6个.调试了老半天.最终出来了,代码例如以下: <SCRIPT LANGUAGE="JavaScr ...

  5. UVA 10025(数学)

     The ? 1 ? 2 ? ... ? n = k problem  The problem Given the following formula, one can set operators ' ...

  6. 用Java做的类似皇家守卫战的游戏

    最近因为数据结构的课设缘故,所以用Java做了一款类似皇家守卫战(本人最钟情的一款PC兼手游的塔防游戏)的游戏.现在把这个游戏放出来,可以下载下来 玩耍 学习,代码中我也做了大量的注释.(运行游戏得带 ...

  7. Highcharts构建空饼图

    Highcharts构建空饼图 空饼图就是不包括不论什么节点的饼图. 在Highcharts中,假设数据列不包括数据,会自己主动显示空白. 这样浏览者无法推断当前图表为什么类型.绘制一个空饼图的变通方 ...

  8. oracle ash性能报告的使用方法

    活动会话历史报告活动会话历史v$active_session_history视图提供了在实例级别抽取会话活动信息.活动会话每分钟会被抽样一次且被存储在sga中的循环缓冲区中.任何被连接到数据库且正等待 ...

  9. linux 免密登陆(超简单)

    一.客户端生产公钥 在windwos上 生成公钥私钥前,先下载git哦 ssh-keygen -t rsa# 记住下方方框内公钥保存地址, 二.查看自己用户的登录地址 cat /etc/passwd ...

  10. 09-JavaScript高级

    今日知识 1. Dom(文档对象模型) 2. Bom(浏览器对象模型) 3. 总结 Dom 1. 获取id为div1的元素对象. * var result=document.getElementByI ...