[JLOI2015]城池攻占 左偏树
下面讲做法: 首先我们可以观察到每个骑士都是独立的,因此对于每个城池我们可以建一个堆,堆中维护的是在这个城池的骑士。
维护一个小根堆,所以如果堆顶的骑士攻击力不够的话,就可以直接pop掉,并且给城池死亡人数统计++(dead),这样用while pop完后,堆里的骑士就都是可以占领这个城池的了,
由于下面的骑士可以上来,所以这个堆要支持合并,所以我们用左偏树
因为pop完后剩下的都是合法的,所以这个时候我们就可以对剩下的骑士进行修改了。但是我们观察到,骑士很多,城池也很多,直接修改显然不太妥当。于是我们借鉴线段树的lazy标记,但是由于这里有乘法也有加法,所以我们维护两个标记,一个mul(乘法标记),一个lazy(加法标记),
由于(x+h)q=xq+hq,所以我们可以把h当做lazy,x当做当前值,q是mul,所以我们更改和下传乘法标记的时候,要同时把lazy也=mul,
这时lazy==hq,mul==q,因此我们要得到xq+h*q这个结果,我们需要先乘后加
deadin[i]代表骑士i死在哪里了,dead代表死在这个城池的人数,keep是城市的生命值,其他数组应该都好懂了
因为我们观察到如果还要下传一个标记won来标记骑士又占领了一个城池的话显然是不划算的,因为mul和lazy之所以有必要就是因为过程中要用到,而won标记仅仅是最后要用而已,并且由于骑士的前进路径是一条链,所以我们直接用死亡城市深度-出发城市深度就可以得到攻占几座城了,如果没死的话死亡城市就是0,因此为了维护死亡城市-出发城市这个式子的正确性,我们的deep统计从1开始
如果还有不懂的就看代码吧,还是有少量注释的
推荐写之前先写线段树2(luogu3373),有利于理解如何同时维护乘法和加法标记,这里的标记本质上是一样的,但是注意不要像我一样,写完线段树2,pushdown就全写成线段树版本的,,,,于是就各种错,,,
下面的输出格式是为了方便我调试改的,所以。。。。
写的可能比较复杂???
表示并不知道为什么我的代码一直比别人长。。。。
-------2018.10.11-------优化了代码格式
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define AC 300050 5 #define LL long long 6 #define D printf("line in %d\n",__LINE__); 7 int n, m; 8 int date[AC], Next[AC], Head[AC], tot, cnt;//前向星 9 LL v[AC], keep[AC]; 10 int deep[AC], a[AC], dead[AC], deadin[AC];//城池属性, 答案 11 int b[AC], root[AC]; 12 13 inline LL read() 14 { 15 LL x = 0; char c = getchar(); bool z = false; 16 while(c > '9' || c < '0') 17 { 18 if(c == '-') z = true; 19 c = getchar(); 20 } 21 while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); 22 if(!z) return x; 23 else return -x; 24 } 25 26 inline void add(int f, int w) 27 { 28 date[++tot] = w, Next[tot] = Head[f], Head[f] = tot; 29 } 30 31 struct left_heap 32 { 33 LL s[AC], mul[AC], lazy[AC];//骑士属性和标记,error!!!标记也要LL啊啊啊啊啊啊啊啊,因为标记也可能乘到很大啊,比如lazy和mul各种乘之类的 34 int l[AC], r[AC], num[AC]; 35 36 inline void pushdown(int x) 37 { 38 int ll = l[x], rr = r[x];//error!!!这又不是线段树啊!!!!干嘛乘2啊 39 if(!mul[x]) return ;//如果mul为0,说明没有这个堆,所以 40 if(mul[x] != 1) 41 { 42 s[ll] *= mul[x], mul[ll] *= mul[x], lazy[ll] *= mul[x];//error!!!加法标记也要乘啊!!! 43 s[rr] *= mul[x], mul[rr] *= mul[x], lazy[rr] *= mul[x]; 44 mul[x] = 1; 45 } 46 if(lazy[x]) 47 { 48 s[ll] += lazy[x], lazy[ll] += lazy[x]; 49 s[rr] += lazy[x], lazy[rr] += lazy[x]; 50 lazy[x]=0;//error!!!不是线段树啊,,,,r,l不是区间了 51 } 52 } 53 54 inline void change_add(int x, int k) 55 { 56 if(!x) return ; 57 s[x] += k, lazy[x] += k; 58 } 59 60 inline void change_mul(int x, int k) 61 { 62 if(!x) return ; 63 s[x] *= k, lazy[x]*=k, mul[x]*=k; 64 } 65 66 int merge(int x, int y) 67 { 68 pushdown(x), pushdown(y); 69 if(!x || !y) return x + y; 70 // pushdown(x),pushdown(y); 71 if(s[x] > s[y]) swap(x, y); 72 r[x] = merge(r[x], y); 73 swap(l[x], r[x]); 74 return x; 75 } 76 77 void pop(int &x) 78 { 79 x=merge(l[x], r[x]); 80 } 81 82 inline void insert(int x, int k) 83 { 84 s[++cnt] = x, num[cnt] = k, mul[cnt] = 1; 85 root[b[k]] = merge(cnt, root[b[k]]); 86 } 87 }heap; 88 89 void DFS(int x) 90 { 91 /* if(a[x]) heap.change_mul(root[x],v[x]); 92 else heap.change_add(root[x],v[x]); 93 if(!Head[x]) return ;//如果到叶节点就返回,因为没有儿子给它了 94 */ 95 R now; 96 for(R i = Head[x]; i; i = Next[i]) 97 { 98 99 now = date[i], deep[now] = deep[x] + 1; 100 DFS(now); 101 root[x] = heap.merge(root[now], root[x]); 102 } 103 while(root[x] && heap.s[root[x]] < keep[x]) 104 { 105 dead[x] ++; 106 deadin[heap.num[root[x]]] = x; 107 heap.pop(root[x]); 108 } 109 if(a[x]) heap.change_mul(root[x], v[x]); 110 else heap.change_add(root[x], v[x]); 111 } 112 113 void pre() 114 { 115 int aa; 116 n = read(), m = read(); 117 deep[1] = 1; 118 for(R i = 1; i <= n; i ++) keep[i] = read(), heap.mul[i] = 1; 119 for(R i = 2; i <= n; i ++) 120 { 121 aa = read(), a[i] = read(), v[i] = read(); 122 add(aa, i); 123 } 124 for(R i = 1; i <= m; i ++) 125 { 126 aa = read(), b[i] = read(); 127 // printf("%d %d\n",aa,b[i]); 128 if(aa >= keep[b[i]])//如果第一座城池打得下才建堆 129 { 130 if(!root[b[i]]) 131 { 132 root[b[i]] = ++cnt;//应该要给城池开堆,堆里存士兵,不然士兵在哪个城市有上面区别 133 heap.num[cnt] = i, heap.s[cnt] = aa, heap.mul[cnt] = 1;//因为是给城池开的堆,所以就要存编号了 134 //printf("%d\n",i); 135 } 136 else heap.insert(aa, i); 137 } 138 else dead[b[i]] ++, deadin[i] = b[i];//不然就别来了 139 } 140 } 141 142 void work() 143 { 144 for(R i = 1; i <= n; i ++) printf("%d\n", dead[i]); 145 printf("\n"); 146 for(R i = 1; i <= m; i ++) 147 printf("%d\n", deep[b[i]] - deep[deadin[i]]); 148 } 149 150 int main() 151 { 152 freopen("in.in","r",stdin); 153 pre(); 154 DFS(1); 155 work(); 156 fclose(stdin); 157 return 0; 158 }
View Code
转载于:https://www.cnblogs.com/ww3113306/p/8759040.html
[JLOI2015]城池攻占 左偏树相关推荐
- BZOJ4003 [JLOI2015]城池攻占 左偏树 可并堆
欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4003 题意概括 题意有点复杂,直接放原题了. 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑 ...
- 【左偏树】【P3261】 [JLOI2015]城池攻占
Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其 ...
- 【学习笔记】浅谈短小可爱的左偏树(可并堆)
文章目录 左偏树 左偏树的合并(merge)操作 例题 罗马游戏 [Apio2012]dispatching [JLOI2015]城池攻占 [Baltic2004]sequence 左偏树 左偏树是一 ...
- 《程序设计解题策略》——1.6 利用左偏树实现优先队列的合并
本节书摘来自华章计算机<程序设计解题策略>一书中的第1章,第1.6节,作者:吴永辉 王建德 更多章节内容可以访问云栖社区"华章计算机"公众号查看. 1.6 利用左偏树实 ...
- 【洛谷3377】 左偏树(可并堆)
前言 其实我是不小心翻线性基的时候看见的. Solution 左偏树只会模板,挖坑待补 代码实现 #include<stdio.h> #include<stdlib.h> #i ...
- P3642 [APIO2016]烟火表演(左偏树、函数)
解析 感觉是左偏树的神题了. 首先有一个比较显然的结论,一个合法的方案中,两个叶子到它们 lca\text{lca}lca 的距离必须相等. 考虑设计 dp\text{dp}dp : fi,xf_{i ...
- YbtOJ#631-次短路径【左偏树,最短路】
正题 题目链接:https://www.ybtoj.com.cn/contest/114/problem/1 题目大意 给出nnn个点mmm条边的一张无向图,对于每个点iii求不经过i∼1i\sim ...
- P4331-[BalticOI2004]Sequence数字序列【左偏树】
正题 题目链接:https://www.luogu.com.cn/problem/P4331 题目大意 给出一个序列aaa,求一个单调上升的序列bbb使得∑i=1n∣ai−bi∣\sum_{i=1}^ ...
- P1552-[APIO2012]派遣【左偏树】
正题 题目链接:https://www.luogu.com.cn/problem/P1552 题目大意 一个nnn个点森林,每个点有价值和代价,选择一个点并在这个点的子树中选择一些点使得. 选择的点数 ...
- P3377-[模板]左偏树(可并堆)
正题 题目链接:https://www.luogu.com.cn/problem/P3377 题目大意 开始时nnn个只有一个数的集合,要求支持 合并两个集合 查询一个集合中的最小值并删除 解题思路 ...
最新文章
- Zabbix(六):项目实战之--自动发现nginx调度器及后端web服务集群、自定义参数监控...
- 我也是一个线程,为什么每天累得像狗一样?
- 关于删除数据仓库的数据
- 初级数据分析师需要哪些必备技能?
- 做网站用UTF-8还是GB2312?
- 小波包能量matlab,小波包分析和小波包能量介绍.doc
- Redis简介及配置文件介绍
- 2018/7/31-zznuoj-问题 A: A + B 普拉斯【二维字符串+暴力模拟+考虑瑕疵的题意-0的特例】...
- c语言统计计算机专业人数,非计算机专业C语言练习题及2013版中国统计年鉴1.doc...
- docker 部署 gitlab最新版本( 当前 11.8.1通过验证)
- 优启通制作系统u盘_优启通 v3.6.2020.0620 VIP版/免费版-好用的U盘启动盘制作工具...
- GPS 经纬度换算方法和定位误差计算
- C#导出EXCEL没有网格线的解决方法
- Access键盘快捷键大全(一)
- Android 全仿To圈儿录音界面实现
- 将前端传过来的base64加密图片保存到本地,并且判断来自于哪个终端
- Machine Learning-L13-频繁模式挖掘
- Mac 使用音频工具分析音频数据
- 最简单的机器学习入门:线性回归
- 【Java容器】Java容器入门教程
热门文章
- C# 之 Stream 和 byte[] 的相关转换
- Nginx 笔记与总结(4)配置 server 访问日志
- Hadoop1.2.1源码解析系列:JT与TT之间的心跳通信机制——命令篇
- jQuery CSS 操作函数
- python源码中的学习笔记_第8章_函数
- 论文写不出来,导师放养,严重焦虑,怎么办?
- 【招聘】哈工大讯飞联合实验室2022届提前批校园招聘
- 【NLP 算法岗】提前批暑期实习面(试)经(历)
- 【收藏】这个时候才是最好的自学时间!深度学习-机器学习-GNN-NLP等AI课程超级大列表汇总,拿走不谢...
- 分类问题的label为啥必须是 one hot 形式?