长跑

Description

  某校开展了同学们喜闻乐见的阳光长跑活动。为了能“为祖国健康工作五十年”,同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑运动。一时间操场上熙熙攘攘,摩肩接踵,盛况空前。
  为了让同学们更好地监督自己,学校推行了刷卡机制。
  学校中有n个地点,用1到n的整数表示,每个地点设有若干个刷卡机。
  有以下三类事件:
  1、修建了一条连接A地点和B地点的跑道。
  2、A点的刷卡机台数变为了B。
  3、进行了一次长跑。问一个同学从A出发,最后到达B最多可以刷卡多少次。具体的要求如下:
  当同学到达一个地点时,他可以在这里的每一台刷卡机上都刷卡。但每台刷卡机只能刷卡一次,即使多次到达同一地点也不能多次刷卡。
  为了安全起见,每条跑道都需要设定一个方向,这条跑道只能按照这个方向单向通行。最多的刷卡次数即为在任意设定跑道方向,按照任意路径从A地点到B地点能刷卡的最多次数。

Input

  输入的第一行包含两个正整数n,m,表示地点的个数和操作的个数。
  第二行包含n个非负整数,其中第i个数为第个地点最开始刷卡机的台数。
  接下来有m行,每行包含三个非负整数P,A,B,P为事件类型,A,B为事件的两个参数。
  最初所有地点之间都没有跑道。
  每行相邻的两个数之间均用一个空格隔开。表示地点编号的数均在1到n之间,每个地点的刷卡机台数始终不超过10000,P=1,2,3。

Output

  输出的行数等于第3类事件的个数,每行表示一个第3类事件。如果该情况下存在一种设定跑道方向的方案和路径的方案,可以到达,则输出最多可以刷卡的次数。如果A不能到达B,则输出-1。

码了一整个下午,终于过了样例,结果AC了……这题样例好强大。。

题解:
“为了安全起见,每条跑道都需要设定一个方向,这条跑道只能按照这个方向单向通行。最多的刷卡次数即为在任意设定跑道方向,按照任意路径从A地点到B地点能刷卡的最多次数。” 这句话是关键。因此,路途中经过的任意一个强联通分量的所有点权之和要全部加上。于是我们就动态维护强联通分量。开2个并查集,一个保存的是原树之间的关系用来判断连通性,一个保存的是强联通分量的代表节点。至于为什么要用第一个并查集,原因是…加速。于是每连一条边u-v,就用第一个并查集判断一下u,v是否连通。如果没有,就直接连接,否则意味着图中出现了一个环。于是,我们把这个环上的所有节点(也就是原来u-v的路径上的所有点)的点权移到一个代表节点上,然后丢掉其他所有点,还要把所有点的第二个并查集的父亲赋值为代表节点,因为它们属于的强联同分量改变了。怎么删除不要的点呢?只要保证不会在各种操作的时候跳到不要的节点即可。具体实现时,只要把所有的fa改为find(fa)即可,就会跳到代表节点上。剩下两个操作都是经典操作。不知道有没有什么更快的方法,但可以肯定的是,我的代码常数巨大==
代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=150005;
int n,m,op,u,v,fu0,fv0,fu1,fv1,pa[N][2],fa[N],ch[N][2],rev[N],val[N],sumv[N];
int a[N],stk[N];
int find(int u,int md){return u==pa[u][md]?u:pa[u][md]=find(pa[u][md],md);
}
bool isroot(int u){if(!fa[u]){return true;}int tmp=find(fa[u],1);return u!=ch[tmp][0]&&u!=ch[tmp][1];
}
int which(int u){return u==ch[find(fa[u],1)][1];
}
void pushup(int u){if(!u){return;}sumv[u]=val[u]+sumv[ch[u][0]]+sumv[ch[u][1]];
}
void reverse(int u){rev[u]^=1;swap(ch[u][0],ch[u][1]);
}
void downtag(int u){if(rev[u]){if(ch[u][0]){reverse(ch[u][0]);}if(ch[u][1]){reverse(ch[u][1]);}rev[u]=0;}
}
void pushdown(int u){stk[stk[0]=1]=u;for(;!isroot(u);u=fa[u]){stk[++stk[0]]=fa[u];}while(stk[0]){downtag(stk[stk[0]--]);}
}
void rotate(int x){int y=find(fa[x],1),z=find(fa[y],1),md=x==ch[y][1];if(y==ch[z][0]||y==ch[z][1]){ch[z][y==ch[z][1]]=x;}fa[x]=z;ch[y][md]=ch[x][!md];if(ch[y][md]){fa[ch[y][md]]=y;}ch[x][!md]=y;if(y){fa[y]=x;}pushup(y);pushup(x);
}
void splay(int u){pushdown(u);while(!isroot(u)){if(!isroot(fa[u])){rotate(which(fa[u])==which(u)?fa[u]:u);}rotate(u);}
}
void access(int u){for(int v=0;u;v=u,u=find(fa[u],1)){splay(u);ch[u][1]=v;pushup(u);}
}
void makeroot(int u){access(u);splay(u);reverse(u);
}
int dfs(int rt,int u){if(!u){return 0;}pa[u][1]=rt;return dfs(rt,ch[u][0])+dfs(rt,ch[u][1])+val[u];
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){pa[i][0]=pa[i][1]=i;}for(int i=1;i<=n;i++){scanf("%d",&a[i]);sumv[i]=val[i]=a[i];}for(int i=1;i<=m;i++){scanf("%d%d%d",&op,&u,&v);if(op==1){if((fu1=find(u,1))!=(fv1=find(v,1))){if((fu0=find(u,0))!=(fv0=find(v,0))){makeroot(fu1);fa[fu1]=fv1;pa[fv0][0]=fu0;}else{makeroot(fu1);access(fv1);splay(fv1);val[fu1]=dfs(fu1,fv1);fa[fu1]=0;ch[fu1][0]=ch[fu1][1]=0;pushup(fu1);}}}else if(op==2){splay(fu1=find(u,1));val[fu1]-=a[u];a[u]=v;val[fu1]+=a[u];pushup(fu1);}else{if(find(u,0)!=find(v,0)){puts("-1");continue;}fu1=find(u,1),fv1=find(v,1);makeroot(fu1);access(fv1);splay(fv1);printf("%d\n",sumv[fv1]);}}return 0;
}

【bzoj2959】长跑【LCT+并查集】相关推荐

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

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

  2. 【BZOJ2594】水管局长加强版,LCT+并查集+二分查找位置

    Time:2016.05.10 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: LCT维护路径最小值 倒叙处理询问,就相当于往图里面加边. 实时维护最小值,即最小生成树,可以参照魔法 ...

  3. [bzoj4998][LCT][并查集]星球联盟

    Description 在遥远的S星系中一共有N个星球,编号为1-N.其中的一些星球决定组成联盟,以方便相互间的交流.但是,组成 联盟的首要条件就是交通条件.初始时,在这N个星球间有M条太空隧道.每条 ...

  4. [BZOJ3669]-[Noi2014]魔法森林-LCT+并查集

    说在前面 刚刚去写了一道SPFA+网络流的糅合题,1A了 闲着没事干开始翻起了status,发现有人在做水管局长,哇这不是LCT嘛! 然后回头看了一下自己写过的寥寥无几的LCT的题,发现都快要忘了 于 ...

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

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

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

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

  7. [luogu-P4299] 首都(并查集 + LCT动态维护树的重心 / 维护虚儿子信息)

    problem luogu-P4299 solution 本题考察了很经典的模型,运用了很经典的解法. 本题用到了重心的两个性质: 两棵树合并为同一棵树时,新的重心一定在原来两棵树各自重心的路径上. ...

  8. BZOJ 4736 温暖会指引我们前行 LCT+最优生成树+并查集

    题目链接:http://uoj.ac/problem/274 题意概述: 没什么好概述的......概述了题意就知道怎么做了......我懒嘛 分析: 就是用lct维护最大生成树. 然后如果去UOJ上 ...

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

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

  10. bzoj2959 长跑

    LCT新姿势:维护边双连通分量. 题意:给你一张无向图,有加边,改点权操作. 你需要回答的是:从a到b,给每条边任意定向后,能经过的点权之和最大是多少.(每个点只算一次,点权非负). 可以发现,一个边 ...

最新文章

  1. 淘宝高可用高伸缩高性能框架之实现
  2. react循环setstate_react -- 关于兄弟组件触发更新的问题
  3. grads 相关系数_基于小波变换的多聚焦图像融合算法
  4. 走近分形与混沌(part2)-豪斯多夫维数
  5. Django-你想知道的都在这里
  6. MongoDB文件操作(支持大于4M数据)
  7. Linux(11)--(历史命令)Ctrl+r, history,!
  8. axios与ajax对比,vue体系中axios请求对比jquery-ajax请求
  9. ML.NET 发布0.11版本:.NET中的机器学习,具有TensorFlow和ONNX的新功能
  10. Abaqus运行fortan报错:“Error in job Job-1: Problem during compilation - D:\test.for”
  11. 全网最全leafLetAPI中文版
  12. 第二人生的源码分析(三十)UDP接收数据和Windows网络关闭
  13. 浏览器-解决火狐浏览器总是提示Adobe Flash更新的问题
  14. 明天冬瓜哥与你见面畅谈!不用报名直接来!
  15. 糖友控糖是在控什么糖呢
  16. 捷得(Joget DX)产品发展路线图
  17. mini2440中nand falsh的使用
  18. 底层网络知识详解:如何连接外网
  19. 一文读懂堡垒机对企业信息安全起到的重要作用
  20. 如何熟练掌握运用Delft3D建模、水动力模拟方法及在地表水环境影响评价中的实践技术

热门文章

  1. craps赌博游戏的python解法
  2. qlv格式怎么打开,把qlv格式转换成mp4的方法
  3. java qlv转mp4 代码_怎么将qlv格式转换成mp4?教你快速转换视频格式的技巧
  4. java 压制警报_适用于Java开发人员的微服务:监视和警报
  5. vue + echarts 省份地图 以及打包后地图加载不出来(比较详细)
  6. clojure-jack-in : error in process filter: open-network-stream: make client process failed: Connecti
  7. 公众号订阅号如何赚钱
  8. amazeUI的icon图标库
  9. 解决vscode的报错:Java 11 or more recent is required to run the Java extension
  10. DNS域传送漏洞(CVE-2015-5254)