LCT新姿势:维护边双连通分量。

题意:给你一张无向图,有加边,改点权操作。

你需要回答的是:从a到b,给每条边任意定向后,能经过的点权之和最大是多少。(每个点只算一次,点权非负)。

可以发现,一个边双连通分量之内的都可以到达。就相当于在缩点后的树上求路径权值和。

使用LCT动态维护:开两个并查集。

一个维护连通性,一个维护缩点后的代表点。

当我们连接两个已经联通的点的时候,把他们之间的那一条路径上的点所在的边双全部缩到某个代表点上,该点的权值也要相应的变化,然后删掉这一条路径上的其他点。查询和修改就是正常姿势。

具体实现如何缩点:

首先提取这一条链成为一颗splay,然后遍历这个splay并全部把代表点设为某个点(splay的根)。最后把这个树删的只剩根。

那么有些虚边如何处理?要用fa[x]的时候用belong.find(fa[x])即可。权值在并查集里面记录。

你相当于在lct上把这些点删了,所有指向这些点的边都指向了代表点。所以当你重新提取一条链的时候,每个点都是一个代表点,不会有之前被删的点存在。

  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 长跑相关推荐

  1. 【BZOJ2959】【codevs2002】长跑,维护双联通分量

    传送门1 传送门2 思路: 思路巧妙的一道数据结构 题意就是让你维护双联通分量 我一开始的想法是写两个并查集来分别维护连通性和双联通分量里的点,然后通过LCT来维护权值和,但我发现缩点时不是很好搞,而 ...

  2. 为什么说,长跑和爬山能锻炼意志?因为要不停的run,run,run......

    长跑和爬山教会我们的是无论做什么都要坚持,教会我们的是生活的态度. 如果不能体会到这一点,那你长跑的意义就是纯粹的锻炼身体. 中国教育的最大败笔就是教会了人学习,却没教会人思考.

  3. BZOJ 2959: 长跑 解题报告

    2959: 长跑 Description 某校开展了同学们喜闻乐见的阳光长跑活动.为了能"为祖国健康工作五十年",同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑 ...

  4. 2021年寒假将至,教育部致信中小学生家长的一封信:人生如长跑,起步忌冲刺,薄发需厚积

    1月6日,教育部致信全国中小学生家长,建议家长们在寒假期间做好三个"关注".跟我们一起读这封信 尊敬的家长朋友: 2021年我国基础教育又有了新变化,呈现出新面貌!一年来,我们与广 ...

  5. BZOJ 2959: 长跑 [lct 双连通分量 并查集]

    2959: 长跑 题意:字词加入边,修改点权,询问两点间走一条路径的最大点权和.不一定是树 不是树? 把边双连通分量缩为一点! 怎么缩? 用一个并查集维护连通性,另一个并查集维护每个点所在边双的编号, ...

  6. NYOJ 631 冬季长跑

    冬季长跑 时间限制:5000 ms  |  内存限制:65535 KB 难度:4 描述 为了增强大学生的身体素质,校长决定进行冬季长跑.有N个班级要参加冬季长跑,班级的编号从1到N.听说这个消息之后学 ...

  7. 光伏领跑者火热前行 可靠性护航“长跑”

    随着第三批光伏领跑者申报标准的出台,在目前普通电站指标有可能缩水的情况下,2017年8-10GW的光伏领跑者项目又将成为各电站投资商争夺的"红海".光伏领跑者在过去两年时间里为行业 ...

  8. 业余长跑爱好者最后膝盖都怎样了?

    我没跑步的时候,我也是这样的想法! 跑步伤膝盖,容易磨损半月板,年轻跑得欢,年老坐轮椅!说实在的,跑步很累,很多人都不想跑,所以找理由,找借口让自己不跑步,不运动! 从开始跑步到现在,我的跑步公里数早 ...

  9. [BZOJ]2959: 长跑

    题解:   我们考虑一条链时 答案为链上和  路径上有环时  这个环上的点都会产生贡献  然后我们可以 用并查集来维护LCT  有环时直接缩成一个点即可 #include <algorithm& ...

最新文章

  1. java使用POI jar包读写xls文件
  2. Spring Security源码解析(四)—— 过滤器
  3. java大话_大话JAVA(一)
  4. mockito 使用_用Mockito回答
  5. Does taro support react hook?
  6. 大型情感剧集Selenium:3_元素定位 #华为云·寻找黑马程序员#
  7. Centos 7 配置 apache 网站
  8. 这是一个定时器,定时执行一次,用在定时发送邮件
  9. 汉诺塔c 语言程序代码,汉诺塔 (C语言代码)
  10. wordpress 百度主动推送 PHP,WordPress 百度自动推送插件
  11. excel文件分割器
  12. 前后端分离项目,有什么优缺点
  13. 2022年1~8月语音合成(TTS)和语音识别(ASR)论文月报
  14. VS Code开源软件介绍——史上最优秀的 IDE ?
  15. 第三批游戏版号下发 移动安全从业者有话说
  16. android 字符转double,Android String类型转换为float、double和int的工具类方法
  17. 倍福PLC的C++ ADS通讯定义数据类型时注意事项
  18. python发送邮件函数
  19. 小米电视盒服务器维护,告别小白!小米电视/盒子不为人知的设置技巧
  20. 计算机应用基础18在线作业容,东师《计算机应用基础》18秋在线作业2.doc

热门文章

  1. [分享]多个选项卡切换效果
  2. UA MATH571A R语言回归分析实践 多元回归2 医疗费用的决定
  3. PowerDesigner建立UML序列图
  4. 编程打开Windows服务控制管理器
  5. 网页视频播放开发总结
  6. dNet项目数据访问层代码总结
  7. IOS树视图学习总结
  8. 【敏捷个人俱乐部-北京】及【免费敏捷结果线下练习】报名帖
  9. AcWing 199. 余数之和 (除法分块)打卡
  10. 搭建eclipse版的ssm+maven+tk.mybatis+redis及mybatis+spring多数据源配置集成的demo