题意:

  支持加入边,修改点权,询问两点间走一条路径的最大点权和。不一定是树。

分析:

  这个题我们需要知道,假如两点间有环,那么无论如何,这个环上所有的价值都可以被我们获得。

  有环,还有这个性质,我们可以自然而然的想到边双联通分量缩点,但是我们不能对于每次加边就重构一下图,更不能每次询问都求一遍最大路,所以我们就需要一个灵活的LCT来维护我们的操作。

  我们用并查集辅助,用一个并查集维护连通性,再用一个并查集维护每个原始点属于哪个新的边双联通分量。

  当我们连接一条边时,如果两个点不连通,那么我们直接将其连通。

  如果本身已经连通,那么我们就在LCT上把这两个点之间的链搞到一个splay上,然后dfs一遍,把链上所有的点都弄进一个双连通分量里(就是用并查集并起来),继而把这些点从splay上删掉,只留一个根节点,将整个环的价值赋给它。

  修改点权的时候,我们直接把原始点的权值修改,然后算出所在连通分量的总权值应该怎样变化即可。

  至此,回答询问也就是自然而然的事情了。

代码:

 1 #include<bits/stdc++.h>
 2 #define max(a,b,c) max(max(a,b),c)
 3 #define lc(x) t[x][0]
 4 #define rc(x) t[x][1]
 5 using namespace std;
 6 const int N=150005;
 7 int t[N][2],rev[N],val[N],sm[N],fu[N];
 8 int s[N],tp,n,m,k,fa[N],Fa[N],q,v[N];
 9 //并查集----------------------------------------↓
10 int get(int x){
11     return x==fa[x]?x:fa[x]=get(fa[x]);
12 } int Get(int x){
13     return x==Fa[x]?x:Fa[x]=Get(Fa[x]);
14 }
15 //并查集----------------------------------------↑
16 //LCT-------------------------------------------↓
17 void pushup(int x){
18     sm[x]=sm[lc(x)]+sm[rc(x)]+val[x];
19 } void revers(int x){
20     rev[x]^=1;swap(lc(x),rc(x));
21 } void pushdown(int x){
22     if(rev[x]){
23         if(lc(x)) revers(lc(x));
24         if(rc(x)) revers(rc(x));
25     } rev[x]=0;return ;
26 } bool pdrt(int x){
27     return lc(get(fu[x]))!=x&&rc(get(fu[x]))!=x;
28 } void rotate(int x){
29     int y=get(fu[x]);int z=get(fu[y]);
30     int dy=(rc(y)==x),dz=(rc(z)==y);
31     if(!pdrt(y)) t[z][dz]=x;
32     t[y][dy]=t[x][dy^1];fu[t[y][dy]]=y;
33     t[x][dy^1]=y;fu[y]=x;fu[x]=z;pushup(y);
34 } void splay(int x){
35     s[++tp]=x;
36     for(int i=x;!pdrt(i);i=fu[i])
37     s[++tp]=get(fu[i]);
38     while(tp) pushdown(s[tp--]);
39     while(!pdrt(x)){
40         int y=get(fu[x]);int z=get(fu[y]);
41         if(!pdrt(y))
42         if(rc(y)==x^rc(z)==y) rotate(x);
43         else rotate(y);rotate(x);
44     } pushup(x);
45 } void access(int x){
46     for(int i=0;x;x=get(fu[x]))
47     splay(x),rc(x)=i,i=x;
48 } void mkrt(int x){
49     access(x);splay(x);revers(x);
50 } int fdrt(int x){
51     access(x),splay(x);
52     while(lc(x)) pushdown(x),x=lc(x);
53     return x;
54 } void split(int x,int y){
55     mkrt(x);access(y);splay(y);
56 } void link(int x,int y){
57     mkrt(x);if(fdrt(y)!=x) fu[x]=y;
58 } void cut(int x,int y){
59     mkrt(x);
60     if(fdrt(y)==x&&fu[y]==x&&!rc(x))
61     fu[x]=t[y][0]=0;pushup(y);
62 }
63 //LCT-------------------------------------------↑
64 //DFS-------------------------------------------↓
65 void dfs(int x,int y){
66     fa[x]=y;pushdown(x);
67     if(lc(x)) dfs(lc(x),y);
68     if(rc(x)) dfs(rc(x),y);
69 }
70 //DFS-------------------------------------------↑
71 int main(){
72     scanf("%d%d",&n,&m);
73     for(int i=1;i<=n;i++)
74     scanf("%d",&v[i]),Fa[i]=i,
75     val[i]=s[i]=v[i],fa[i]=i;
76     for(int i=1,op,a,b;i<=m;i++){
77         scanf("%d%d%d",&op,&a,&b);
78         if(op==1){
79             a=get(a),b=get(b);
80             if(a==b) continue;
81             split(a,b);
82             if(Get(a)!=Get(b))
83             fu[a]=b,Fa[Fa[a]]=Fa[b];
84             else val[b]=sm[b],dfs(b,b),
85             t[b][0]=t[b][1]=0;
86         } int d;if(op==2)
87         d=a,a=get(a),splay(a),
88         val[a]+=b-v[d],v[d]=b,pushup(a);
89         if(op==3){
90             a=get(a),b=get(b);
91             if(Get(a)!=Get(b)) puts("-1");
92             else split(a,b),printf("%d\n",sm[b]);
93         }
94     } return 0;
95 }

LCT

转载于:https://www.cnblogs.com/Alan-Luo/articles/10157263.html

BZOJ 2959 长跑 LCT+动态边双相关推荐

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

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

  2. BZOJ 2959 长跑 (LCT、并查集)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2959 题解 真是被这题搞得心态大崩--调了7个小时--然而并查集都能写成\(O(n^2) ...

  3. bzoj 2959: 长跑(LCT+并查集)

    2959: 长跑 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 315  Solved: 178 [Submit][Status][Discuss] ...

  4. BZOJ 2959: 长跑 解题报告

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

  5. [BZOJ]2959: 长跑

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

  6. 【刷题】BZOJ 2959 长跑

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

  7. BZOJ 2959 - 长跑

    题意 每个点有各自的权值,要求维护操作:动态加边.动态修改权值.询问在每个点只能经过一次的情况下两点间路程中的最大权值和 题解 首先对于一个静态的图,将其缩点,可以得到一棵树,那么两点间询问的答案即为 ...

  8. 如何为***选择合适的动态密码双因素认证方案

    CKEY动态密码认证是双因子认证的一种方式,×××用户增加动态密码认证,借助此方案可以提升×××远程拨入安全,加强登陆用户审计. CKEY为×××提供短信密码.硬件令牌.软件令牌.短信密码+硬件令牌混 ...

  9. HYSBZ - 2959 长跑(动态树+并查集)

    某校开展了同学们喜闻乐见的阳光长跑活动.为了能"为祖国健康工作五十年",同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑运动.一时间操场上熙熙攘攘,摩肩接踵,盛况 ...

最新文章

  1. datagrid DataFormatString
  2. 人天生就会除法,宾大最新研究:儿童啥都不学也能算出来
  3. matlab极大值点个数,求一组数的极大值个数
  4. 卓越软件工程--《微软360度》读后感
  5. [转]马云在《赢在中国》对创业者的经典点评
  6. 教学目标四个维度_挖掘教材 预设目标 思本归真—— 记临安区初二英语教学研讨会...
  7. 双代号网络图基础算法_最新(免锁版)网络图横道图绘制软件,内附安装教程,制图做更快...
  8. (转)Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法
  9. 新年发财专属红包封面,高端大气上档次!
  10. 手把手教你制作easyUI+bootstrap工作站,主要学习tabs方法
  11. c语言,求素数个数,关于求素数个数的话题
  12. typescript面试题_vue 248+个知识点(面试题)为你保驾护航
  13. 2022年上半年系统分析师上午真题及答案解析
  14. Django之jsonp跨域请求原理
  15. 课堂派题库格式转换程序
  16. Github项目精选:2021年6月优秀项目推荐
  17. Java返回Json文件
  18. 国产之路:复旦微调试笔记3:环境配置
  19. SiteMap(站点地图)
  20. 计算机科学与技术专业学长,2017级计算机科学与技术专业成功举办优秀就业学长经验交流会...

热门文章

  1. 忽略非数据库字段的注解
  2. 【性能】【内存】zram解读
  3. java逻辑运算符之异或
  4. ASO优化之关于应用宝的关键词排名
  5. 洛谷 P2756 飞行员配对方案问题 二分图 匈牙利算法 链式前向星 汉子找妹子模型 最大流模板 FF算法
  6. 闲鱼java系统_java爬取闲鱼商品信息(一)
  7. 修改WIN10D盘默认盘符
  8. 1:9 error Component name ““ should always be multi-word
  9. 云时代架构之点融支付系统架构的演进
  10. 不同表格查找重复数据VBA