城池攻占 bzoj-4003 JLOI-2015

    题目大意:一颗n个节点的有根数,m个有初始战斗力的骑士都站在节点上。每一个节点有一个standard,如果这个骑士的战斗力超过了这个门槛,他就会根据城池的奖励增加自己的战斗力。具体地:每一个城池有一个flag和一个val,表示成功到达这个城市的骑士的战斗力会乘上val还是加上val。每个骑士都只会向根节点进攻。输出每个骑士败北的城市编号。如果这个骑士成功到达根节点,输出0。

    注释:$1\le n,m \le 3\cdot 10^5$,$-10^{18}\le standard , val , attack \le 10^{18}$。保证每一个骑士的atk不大于longlong。

      想法:GXZlegend可并堆例题。和上两道题类似地,我们对于每一个城池维护一个小根堆,元素是是当前节点为子树里的骑士到达这里的atk,我们自底向顶修改城墙,顺便将骑士向上推,以及标记的下传。我们在merge函数中完成pushdown的操作。特别地,在维护双标记的时候我默认是先乘后加,所以在pushdown的时候如果发现有乘法标记的话需要先将加法标记扩大,再下传。

    最后,附上丑陋的代码... ...

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 300010
using namespace std;
typedef long long ll;
int head[N],to[N],type[N],next[N],cnt,root[N],l[N],r[N],d[N],deep[N],from[N],kill[N],atk[N];
ll val[N],h[N],key[N],tadd[N],tmul[N];
inline void add(int x,int y,int a,ll b)
{
to[++cnt]=y;
type[cnt]=a;
val[cnt]=b;
next[cnt]=head[x];
head[x]=cnt;
}
inline void pushdown(int x)
{
if(!x)return;
if(tmul[x]!=1)
{
key[l[x]]*=tmul[x];tadd[l[x]]*=tmul[x];tmul[l[x]]*=tmul[x];
key[r[x]]*=tmul[x];tadd[r[x]]*=tmul[x];tmul[r[x]]*=tmul[x];
tmul[x]=1;
}
if(tadd[x])
{
key[l[x]]+=tadd[x];tadd[l[x]]+=tadd[x];
key[r[x]]+=tadd[x];tadd[r[x]]+=tadd[x];
tadd[x]=0;
}
}
int merge(int x,int y)
{
if(!x) return y;
if(!y) return x;
pushdown(x),pushdown(y);
if(key[x]>key[y]) swap(x,y);
r[x]=merge(r[x],y);
if(d[l[x]]<d[r[x]]) swap(l[x],r[x]);
d[x]=d[r[x]]+1;
return x;
}
void dfs(int x)
{
for(int i=head[x];i;i=next[i])
{
deep[to[i]]=deep[x]+1;
dfs(to[i]);
if(type[i])
{
key[root[to[i]]]*=val[i];
tadd[root[to[i]]]*=val[i];
tmul[root[to[i]]]*=val[i];
}
else
{
key[root[to[i]]]+=val[i];
tadd[root[to[i]]]+=val[i];
}
root[x]=merge(root[x],root[to[i]]);
}
while(root[x]&&key[root[x]]<h[x])
{
kill[x]++,atk[root[x]]=x,pushdown(root[x]),root[x]=merge(l[root[x]],r[root[x]]);
}
}
int main()
{
int n,m,x,a;
ll b;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&h[i]);
for(int i=2;i<=n;i++) scanf("%d%d%lld",&x,&a,&b),add(x,i,a,b);
for(int i=1;i<=m;i++)
{
tmul[i]=1,scanf("%lld%d",&key[i],&from[i]),root[from[i]]=merge(root[from[i]],i);
}
d[0]=-1,deep[1]=1;
dfs(1);
for(int i=1;i<=n;i++)
{
printf("%d\n",kill[i]);
}
for(int i=1;i<=m;i++)
{
printf("%d\n",deep[from[i]]-deep[atk[i]]);
}
return 0;
}

    小结:type标记存在哪里都无所谓qwq

  

[bzoj4003][JLOI2015]城池攻占_左偏树的更多相关文章

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

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

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

    传送门 每一个城市代表的点开一个小根堆,把每一个骑士合并到它开始攻占的城池所代表的点上 然后开始dfs,每一次把子树里那些还活着的骑士合并上来 然后再考虑当前点的堆,一直pop直到骑士全死光或者剩下的 ...

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

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

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

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

  5. BZOJ4003 JLOI2015城池攻占

    用左偏树模拟攻占的过程,维护最小值,最多入和出m次,每次log复杂度. #include<bits/stdc++.h> using namespace std; ; typedef lon ...

  6. [bzoj1455]罗马游戏_左偏树_并查集

    罗马游戏 bzoj-1455 题目大意:给你n个人,2种操作,m次操作:1.将i号士兵所在的集合的最小值删除 2.合并i和j两个士兵所在的团体 注释:$1\le n\le 10^6$,$1\le m ...

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

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

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

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

  9. BZOJ4003[JLOI2015]城池攻占——可并堆

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

随机推荐

  1. php排序函数测试

    1.sort,asort,arsort函数 十万个数的数组排序,用了0.17秒 $starttime=explode(' ',microtime());;for ($i=0; $i <10000 ...

  2. P4049 [JSOI2007]合金

    传送门 我数学可能白学了-- 因为三个数加起来等于\(1\),那么只要用前两个数就能表示,那么就能把每一种金属看成一个二维向量.考虑只有两个向量的时候,设这两个向量为\(a,b\),那么一个向量\(c ...

  3. [Swift通天遁地]九、拔剑吧-(17)创建一个三维折叠样式的页面展开效果

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  4. VUE使用QRcode或者vue-qr生成二维码

    这里介绍两种vue生成二维码的方法 QRcode vue-qr vue-qr比QRcode功能多在可以在中间加logo 下面先介绍QRcode vue里安装qrcodejs的npm包 npm inst ...

  5. Spinner的样式大致简介

    Spinner Spinner 是一个列表选择框,会在用户选择后,展示一个列表供用户进行选择.Spinner是ViewGroup的间接子类,它和其他的Android控件一样,数据需要使用Adapter ...

  6. Codeforces 771C

    我的树形dp果然是渣... 题意:给一棵树,共n(0<n<=15e4)个节点,可在树上进行跳跃,每次跳的最大距离为k(0<k<=5),定义f(s,t)为(dis(s,t)+k) ...

  7. JS高级——递归

    基本概念 1.在函数内调用函数自己,就是递归 2.没有递归结束条件的递归,就是死递归 3.化归思想,将一个问题由难化易,由繁化简,由复杂化简单的过程称为化归,它是转化和归结的简称. 基本使用 1.计算 ...

  8. JS高级——逻辑中断

    1.表达式1||表达式2:表达式1为真,返回表达式1:表达式1为假,返回表达式2 2.表达式1&&表达2:表达式1为真,返回表达式2:表达式1为假,返回表达式1

  9. JS实现随机颜色的3种方法与颜色格式的转化

    JS实现随机颜色的3种方法与颜色格式的转化   随机颜色和颜色格式是我们在开发中经常要用到的一个小功能,网上相关的资料也很多,想着有必要总结一下自己的经验.所以这篇文章主要介绍了JS实现随机颜色的3种 ...

  10. Python 之lxml解析库

    一.XPath常用规则 二.解析html文件 from lxml import etree # 读取HTML文件进行解析 def parse_html_file(): html = etree.par ...