不得不说,这道题目是真的难,真不愧它的“省选/NOI-”的紫色大火题!!!

花了我晚自习前半节课看题解,写代码,又花了我半节晚自习调代码,真的心态爆炸。基本上改得和题解完全一样了我才过了这道题!真的烦。没事,那接下来我来完全把这道题搞透。

左偏树总结

Part 1 理解题目

至少我一开始不知道为什么要用左偏树,甚至我看题解一开始也都没弄懂,所以先把题目弄清楚。
首先我们由题可以知道,这要求我们从建好的树的叶子节点开始往上推,有些骑士到特定的点才会出现,check一下骑士能否攻占城池,再记录进答案,更新战斗力,这就很容易想到左偏树可并堆了。

Part 2 解题思想

既然每到一个点会出现一堆的新骑士,所以我们可以在那些点连一些“隐藏边”,到这个点时用链式前向星扫一遍加到一个小根堆中,然后把这个点以下的所有剩下的骑士合并到这个堆中(板子),然后在check时挨个弹出堆顶,如果不能占领就记入答案,能占领我们就要考虑更新骑士,我们不可能直接更新整个堆中的骑士,这样会被硬生生卡成O(n)的修改,所以我们考虑放一个lazy标记在堆顶,每一次合并和删除的时候再下放就可以了。

part 3 code

    #include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<ctime>
#include<queue>
#include<stack>
#define lst long long
#define rg register
#define N 300050
using namespace std; int n,m,cnt;
bool type[N];
int fir[N],deep[N],up[N],dead[N];
lst key[N],def[N],v[N],mul[N],plu[N];
struct edge{
int to,nxt;
}a[N],b[N];
int head[N],ft[N],ls[N],rs[N],dis[N]; inline lst read()
{
rg lst s=,m=;rg char ch=getchar();
while(ch!='-'&&(ch<''||ch>''))ch=getchar();
if(ch=='-')m=-,ch=getchar();
while(ch>=''&&ch<='')s=(s<<)+(s<<)+ch-'',ch=getchar();
return m*s;
} void cover(rg int A,rg lst c,rg lst j)
{
if(!A)return;
key[A]*=c,key[A]+=j;
mul[A]*=c,plu[A]*=c,plu[A]+=j;
} void pushdown(rg int A)
{
cover(ls[A],mul[A],plu[A]);
cover(rs[A],mul[A],plu[A]);
mul[A]=,plu[A]=;
} int Merge(rg int A,rg int B)
{
if(!A||!B)return A+B;
if(key[A]>key[B])swap(A,B);
pushdown(A),pushdown(B);
rs[A]=Merge(rs[A],B);
if(dis[ls[A]]<dis[rs[A]])swap(ls[A],rs[A]);
dis[A]=dis[rs[A]]+;
return A;
} int Delete(rg int A)
{
pushdown(A);
return Merge(ls[A],rs[A]);
} int dfs(rg int now,rg int fm)
{
rg int A=,B;
deep[now]=deep[fm]+;
for(rg int i=ft[now];i;i=b[i].nxt)A=Merge(A,b[i].to);
for(rg int i=head[now];i;i=a[i].nxt)
{
B=dfs(a[i].to,now);
A=Merge(A,B);
}
while(key[A]<def[now]&&A)
{
dead[now]++;up[A]=deep[now];
A=Delete(A);
}
if(type[now])cover(A,v[now],);
else cover(A,,v[now]);
return A;
} int main()
{
n=read(),m=read();
for(rg int i=;i<=n;++i)def[i]=read();
for(rg int i=;i<=n;++i)
{
rg int go=read();
a[++cnt]=(edge){i,head[go]};head[go]=cnt;
type[i]=read(),v[i]=read();
}cnt=;
for(rg int i=;i<=m;++i)
{
key[i]=read(),fir[i]=read();
b[++cnt]=(edge){i,ft[fir[i]]};ft[fir[i]]=cnt;
}
dfs(,);
for(rg int i=;i<=n;++i)printf("%d\n",dead[i]);
for(rg int i=;i<=m;++i)printf("%d\n",deep[fir[i]]-up[i]);
return ;
}

到此为止,顺便膜拜一下大佬zsy,这是他的城池攻占:

[洛谷P3261] [JLOI2015]城池攻占(左偏树)的更多相关文章

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

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

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

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

  3. [luogu3261 JLOI2015] 城池攻占 (左偏树+标记)

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

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

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

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

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

  6. [洛谷P3261][JLOI2015]城池攻占

    题目大意:有$n$个点的树,第$i$个节点有一个权值$h_i$,$m$个骑士,第$i$个骑士攻击力为$v_i$,一个骑士可以把从它开始的连续的父亲中比它小的节点攻破,攻破一个节点可以把攻击力加或乘一个 ...

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

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

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

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

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

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

随机推荐

  1. Python之路-条件控制&循环语句&列表推导式&常用函数

    一.什么是条件控制语句 条件控制语句,也可以称之为判断语句,通过一条或多条的执行结果来决定接下来要执行的代码块. 二.if语句 if语句是用来进行判断的,最简答的if语句只有一个判断一个操作. 语法: ...

  2. 未能加载文件或程序集“WebApi”或它的某一个依赖项。试图加载格式不正确的程序。

    将项目的平台目标改为“Any CPU” 在项目上右击选择属性——>生成——>平台目标  选择Any CPU

  3. js 一个不得不注意的浏览器兼容性问题 进制转换

    写几行JS代码 var num = '022'; alert(num+' '+parseInt(num)+' '+parseInt(num,10)); 不同的浏览器将会得到不同的结果在谷歌浏览器下的结 ...

  4. Java虚拟机——Class类文件结构

    Class文件格式采用一种类似C语言结构体的结构来存储数据,这种数据结构只有两种数据类型:无符号数和表.      无符号数属于基本的数据类型,数据项的不同长度分别用u1, u2, u4, u8表示, ...

  5. 六、MyBatis-缓存机制

    MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制.缓存可以极大的提升查询效率.MyBatis系统中默认定义了两级缓存, 一级 缓存和 二级缓存.– 1.默认情况下,只有一级缓 ...

  6. phpstorm 调试时浏览器显示The requested resource / was not found on this server

    1.进入thinkphp项目的public 目录运行以下命令即可 root@jiang:/var/www/tp5# php -S localhost:8080 router.php PHP 7.2.2 ...

  7. [POJ1772] Substract

    问题描述 We are given a sequence of N positive integers a = [a1, a2, ..., aN] on which we can perform co ...

  8. HashMap底层代码分析

    public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; //this.loadFactor为加载因子,其值为默认的加载因子常量:DEFAUL ...

  9. 本页面用来演示如何通过JS SDK,创建完整的QQ登录流程,并调用openapi接口

    QQ登录将用户信息存储在cookie中,命名为__qc__k ,请不要占用 __qc__k : 1) :: 在页面顶部引入JS SDK库: 将“js?”后面的appid参数(示例代码中的:100229 ...

  10. 多行文本溢出隐藏处理,兼容ie,火狐

    问题 多行文本溢出隐藏,webkit内核浏览器如谷歌支持如下写法: overflow: hidden; text-overflow: ellipsis; display: -webkit-box; - ...