bzoj2959 长跑
LCT新姿势:维护边双连通分量。
题意:给你一张无向图,有加边,改点权操作。
你需要回答的是:从a到b,给每条边任意定向后,能经过的点权之和最大是多少。(每个点只算一次,点权非负)。
可以发现,一个边双连通分量之内的都可以到达。就相当于在缩点后的树上求路径权值和。
使用LCT动态维护:开两个并查集。
一个维护连通性,一个维护缩点后的代表点。
当我们连接两个已经联通的点的时候,把他们之间的那一条路径上的点所在的边双全部缩到某个代表点上,该点的权值也要相应的变化,然后删掉这一条路径上的其他点。查询和修改就是正常姿势。
具体实现如何缩点:
首先提取这一条链成为一颗splay,然后遍历这个splay并全部把代表点设为某个点(splay的根)。最后把这个树删的只剩根。
那么有些虚边如何处理?要用fa[x]的时候用belong.find(fa[x])即可。权值在并查集里面记录。
你相当于在lct上把这些点删了,所有指向这些点的边都指向了代表点。所以当你重新提取一条链的时候,每个点都是一个代表点,不会有之前被删的点存在。
![](/assets/blank.gif)
![](/assets/blank.gif)
1 #include <cstdio> 2 #include <algorithm> 3 4 const int N = 150010; 5 6 int fa[N], s[N][2], val[N], sum[N], S[N], Sp; 7 bool rev[N]; 8 9 inline void read(int &x) { 10 x = 0; 11 char c = getchar(); 12 while(c < '0' || c > '9') { 13 c = getchar(); 14 } 15 while(c >= '0' && c <= '9') { 16 x = (x << 3) + (x << 1) + c - 48; 17 c = getchar(); 18 } 19 return; 20 } 21 22 struct UFS { 23 int fa[N], Val[N]; 24 inline void init(int n) { 25 for(int i = 1; i <= n; i++) { 26 fa[i] = i; 27 Val[i] = val[i]; 28 } 29 return; 30 } 31 int find(int x) { 32 if(fa[x] == x) { 33 return x; 34 } 35 return fa[x] = find(fa[x]); 36 } 37 inline void merge(int x, int y) { 38 x = find(x); 39 y = find(y); 40 if(x != y) { 41 fa[y] = x; 42 Val[x] += Val[y]; 43 } 44 return; 45 } 46 inline bool check(int x, int y) { 47 return find(x) == find(y); 48 } 49 }ufs, belong; 50 51 inline bool no_root(int x) { 52 int f = belong.find(fa[x]); 53 return (s[f][0] == x) || (s[f][1] == x); 54 } 55 56 inline void pushup(int x) { 57 sum[x] = sum[s[x][0]] + sum[s[x][1]] + belong.Val[x]; 58 return; 59 } 60 61 inline void pushdown(int x) { 62 if(rev[x]) { 63 if(s[x][0]) { 64 rev[s[x][0]] ^= 1; 65 } 66 if(s[x][1]) { 67 rev[s[x][1]] ^= 1; 68 } 69 std::swap(s[x][0], s[x][1]); 70 rev[x] = 0; 71 } 72 return; 73 } 74 75 inline void rotate(int x) { 76 int y = belong.find(fa[x]); 77 int z = belong.find(fa[y]); 78 bool f = (s[y][1] == x); 79 80 fa[x] = z; 81 if(no_root(y)) { 82 s[z][s[z][1] == y] = x; 83 } 84 s[y][f] = s[x][!f]; 85 if(s[x][!f]) { 86 fa[s[x][!f]] = y; 87 } 88 s[x][!f] = y; 89 fa[y] = x; 90 91 pushup(y); 92 pushup(x); 93 return; 94 } 95 96 inline void splay(int x) { 97 int y = x; 98 S[++Sp] = y; 99 while(no_root(y)) { 100 y = belong.find(fa[y]); 101 S[++Sp] = y; 102 } 103 while(Sp) { 104 pushdown(S[Sp]); 105 Sp--; 106 } 107 108 y = belong.find(fa[x]); 109 int z = belong.find(fa[y]); 110 while(no_root(x)) { 111 if(no_root(y)) { 112 (s[z][1] == y) ^ (s[y][1] == x) ? 113 rotate(x) : rotate(y); 114 } 115 rotate(x); 116 y = belong.find(fa[x]); 117 z = belong.find(fa[y]); 118 } 119 return; 120 } 121 122 inline void access(int x) { 123 int y = 0; 124 while(x) { 125 splay(x); 126 s[x][1] = y; 127 pushup(x); 128 y = x; 129 x = belong.find(fa[x]); 130 } 131 return; 132 } 133 134 inline void make_root(int x) { 135 access(x); 136 splay(x); 137 rev[x] = 1; 138 return; 139 } 140 141 inline void link(int x, int y) { 142 make_root(x); 143 fa[x] = y; 144 return; 145 } 146 147 void del(int x, int r) { 148 belong.merge(r, x); 149 if(s[x][0]) { 150 del(s[x][0], r); 151 } 152 if(s[x][1]) { 153 del(s[x][1], r); 154 } 155 s[x][0] = s[x][1] = 0; 156 pushup(x); 157 return; 158 } 159 160 int main() { 161 int n, m; 162 read(n); 163 read(m); 164 for(int i = 1; i <= n; i++) { 165 read(val[i]); 166 } 167 ufs.init(n); 168 belong.init(n); 169 for(int i = 1, x, y, f; i <= m; i++) { 170 read(f); 171 read(x); 172 read(y); 173 if(f == 1) { // link 174 x = belong.find(x); 175 y = belong.find(y); 176 if(!ufs.check(x, y)) { 177 ufs.merge(x, y); 178 link(x, y); 179 } 180 else if(!belong.check(x, y)){ 181 make_root(x); 182 access(y); 183 splay(y); 184 del(y, y); 185 } 186 } 187 else if(f == 2) { // val a -> b 188 int tx = belong.find(x); 189 make_root(tx); 190 belong.Val[tx] += y - val[x]; 191 val[x] = y; 192 pushup(tx); 193 } 194 else { //ask 195 x = belong.find(x); 196 y = belong.find(y); 197 if(!ufs.check(x, y)) { 198 puts("-1"); 199 } 200 else { 201 make_root(x); 202 access(y); 203 splay(y); 204 printf("%d\n", sum[y]); 205 } 206 } 207 } 208 209 return 0; 210 }
AC代码
类似的题还有bzoj4998 星球联盟。
转载于:https://www.cnblogs.com/huyufeifei/p/10175795.html
bzoj2959 长跑相关推荐
- 【BZOJ2959】【codevs2002】长跑,维护双联通分量
传送门1 传送门2 思路: 思路巧妙的一道数据结构 题意就是让你维护双联通分量 我一开始的想法是写两个并查集来分别维护连通性和双联通分量里的点,然后通过LCT来维护权值和,但我发现缩点时不是很好搞,而 ...
- 为什么说,长跑和爬山能锻炼意志?因为要不停的run,run,run......
长跑和爬山教会我们的是无论做什么都要坚持,教会我们的是生活的态度. 如果不能体会到这一点,那你长跑的意义就是纯粹的锻炼身体. 中国教育的最大败笔就是教会了人学习,却没教会人思考.
- BZOJ 2959: 长跑 解题报告
2959: 长跑 Description 某校开展了同学们喜闻乐见的阳光长跑活动.为了能"为祖国健康工作五十年",同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑 ...
- 2021年寒假将至,教育部致信中小学生家长的一封信:人生如长跑,起步忌冲刺,薄发需厚积
1月6日,教育部致信全国中小学生家长,建议家长们在寒假期间做好三个"关注".跟我们一起读这封信 尊敬的家长朋友: 2021年我国基础教育又有了新变化,呈现出新面貌!一年来,我们与广 ...
- BZOJ 2959: 长跑 [lct 双连通分量 并查集]
2959: 长跑 题意:字词加入边,修改点权,询问两点间走一条路径的最大点权和.不一定是树 不是树? 把边双连通分量缩为一点! 怎么缩? 用一个并查集维护连通性,另一个并查集维护每个点所在边双的编号, ...
- NYOJ 631 冬季长跑
冬季长跑 时间限制:5000 ms | 内存限制:65535 KB 难度:4 描述 为了增强大学生的身体素质,校长决定进行冬季长跑.有N个班级要参加冬季长跑,班级的编号从1到N.听说这个消息之后学 ...
- 光伏领跑者火热前行 可靠性护航“长跑”
随着第三批光伏领跑者申报标准的出台,在目前普通电站指标有可能缩水的情况下,2017年8-10GW的光伏领跑者项目又将成为各电站投资商争夺的"红海".光伏领跑者在过去两年时间里为行业 ...
- 业余长跑爱好者最后膝盖都怎样了?
我没跑步的时候,我也是这样的想法! 跑步伤膝盖,容易磨损半月板,年轻跑得欢,年老坐轮椅!说实在的,跑步很累,很多人都不想跑,所以找理由,找借口让自己不跑步,不运动! 从开始跑步到现在,我的跑步公里数早 ...
- [BZOJ]2959: 长跑
题解: 我们考虑一条链时 答案为链上和 路径上有环时 这个环上的点都会产生贡献 然后我们可以 用并查集来维护LCT 有环时直接缩成一个点即可 #include <algorithm& ...
最新文章
- java使用POI jar包读写xls文件
- Spring Security源码解析(四)—— 过滤器
- java大话_大话JAVA(一)
- mockito 使用_用Mockito回答
- Does taro support react hook?
- 大型情感剧集Selenium:3_元素定位 #华为云·寻找黑马程序员#
- Centos 7 配置 apache 网站
- 这是一个定时器,定时执行一次,用在定时发送邮件
- 汉诺塔c 语言程序代码,汉诺塔 (C语言代码)
- wordpress 百度主动推送 PHP,WordPress 百度自动推送插件
- excel文件分割器
- 前后端分离项目,有什么优缺点
- 2022年1~8月语音合成(TTS)和语音识别(ASR)论文月报
- VS Code开源软件介绍——史上最优秀的 IDE ?
- 第三批游戏版号下发 移动安全从业者有话说
- android 字符转double,Android String类型转换为float、double和int的工具类方法
- 倍福PLC的C++ ADS通讯定义数据类型时注意事项
- python发送邮件函数
- 小米电视盒服务器维护,告别小白!小米电视/盒子不为人知的设置技巧
- 计算机应用基础18在线作业容,东师《计算机应用基础》18秋在线作业2.doc