【BZOJ2959】长跑

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。

题解:如果是一棵树,那么直接求两点间路径即可;如果形成了环,那么整个环是可以一起走的,相当于环变成了一个点,我们可以在LCT的过程中维护一个并查集来实现这个过程。

缩环的具体方法:先access+splay使a,b在同一棵splay里,然后DFS整棵splay,将所有点与根的并查集合并,然后将根的儿子清空。这相当于我们直接删除了这些点,但是其它点的fa也会产生变化,所以我们每次调用fa的时候都在并查集中find一下就行了。

注意:判断两点是否连通要再开一个并查集!不能用findroot!

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=150010;
int n,m,tot;
int F[maxn],f[maxn],fa[maxn],rev[maxn],ch[2][maxn],s[maxn],v[maxn],V[maxn];
int find(int x)
{return (f[x]==x)?x:(f[x]=find(f[x]));
}
int Find(int x)
{return (F[x]==x)?x:(F[x]=Find(F[x]));
}
bool isr(int x) {return ch[0][find(fa[x])]!=x&&ch[1][find(fa[x])]!=x;}
void pushup(int x)
{s[x]=s[ch[0][x]]+s[ch[1][x]]+v[x];
}
void pushdown(int x)
{if(rev[x]){swap(ch[0][x],ch[1][x]);if(ch[0][x])    rev[ch[0][x]]^=1;if(ch[1][x])  rev[ch[1][x]]^=1;rev[x]=0;}
}
void updata(int x)
{if(!isr(x))    updata(find(fa[x]));pushdown(x);
}
void rotate(int x)
{int y=find(fa[x]),z=find(fa[y]),d=(x==ch[1][y]);if(!isr(y))   ch[y==ch[1][z]][z]=x;fa[x]=z,fa[y]=x,ch[d][y]=ch[d^1][x];if(ch[d^1][x])   fa[ch[d^1][x]]=y;ch[d^1][x]=y;pushup(y),pushup(x);
}
void splay(int x)
{updata(x);while(!isr(x)){int y=find(fa[x]),z=find(fa[y]);if(!isr(y)){if((x==ch[0][y])^(y==ch[0][z])) rotate(x);else  rotate(y);}rotate(x);}
}
void access(int x)
{for(int y=0;x;splay(x),ch[1][x]=y,pushup(x),y=x,x=find(fa[x]));
}
void maker(int x)
{access(x),splay(x),rev[x]^=1;
}
void dfs(int x,int y)
{f[x]=y;pushdown(x);if(ch[0][x])   dfs(ch[0][x],y);if(ch[1][x])    dfs(ch[1][x],y);
}
int rd()
{int ret=0,f=1;   char gc=getchar();while(gc<'0'||gc>'9')  {if(gc=='-')f=-f;  gc=getchar();}while(gc>='0'&&gc<='9')  ret=ret*10+gc-'0',gc=getchar();return ret*f;
}
int main()
{n=rd(),m=rd();int i,a,b,c,d;for(i=1;i<=n;i++) s[i]=V[i]=v[i]=rd(),F[i]=f[i]=i;for(i=1;i<=m;i++){c=rd(),a=rd(),b=rd();if(c==1){a=find(a),b=find(b);if(a==b)   continue;maker(a),access(b),splay(b);if(Find(a)!=Find(b))  fa[a]=b,F[F[a]]=F[b];else v[b]=s[b],dfs(b,b),ch[0][b]=ch[1][b]=0;}if(c==2)   d=a,a=find(a),splay(a),v[a]+=b-V[d],V[d]=b,pushup(a);if(c==3){a=find(a),b=find(b);if(Find(a)!=Find(b))    printf("-1\n");else   maker(a),access(b),splay(b),printf("%d\n",s[b]);}}return 0;
}//9 31 10 20 30 40 50 60 70 80 90 3 1 2 1 1 3 1 1 2 1 8 9 1 2 4 1 2 5 1 4 6 1 4 7 3 1 8 3 8 8 1 8 9 3 8 8 3 7 5 3 7 3 1 4 1 3 7 5 3 7 3 1 5 7 3 6 5 3 3 6 1 2 4 1 5 5 3 3 6 2 8 180 3 8 8 2 9 190 3 9 9 2 5 150 3 3 6 2 1 210 3 3 6

转载于:https://www.cnblogs.com/CQzhangyu/p/7327651.html

【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. 读书笔记——javascript闭包
  2. mysql myisam innodb 区别
  3. Unity 总裁 John Riccitiello 发话:VR足以匹敌互联网
  4. CVE-2012-1876 Internet Exporter堆溢出漏洞分析
  5. nanflash编程的地址问题
  6. 微信小程序登录页php后台,微信小程序:微信登陆(ThinkPHP作后台)
  7. 深入Spring Boot:快速集成Dubbo + Hystrix
  8. 所有的service报红但不报错_从一个应用报错来看centos系统的/tmp目录自动清理规则...
  9. andriod创建用户界面(1)
  10. 用jframe给MySQL输入数据_如何从JTextField输入Info到sql数据库?
  11. html图片等比例拉伸,CSS控制图片等比例缩放
  12. [论文阅读] (16)Powershell恶意代码检测论文总结及抽象语法树(AST)提取
  13. 博客园文章索引生成器
  14. 设计模式、重构.pdf
  15. Video标签的常用属性操作
  16. P4556 [Vani有约会]雨天的尾巴 树链剖分 线段树合并
  17. 视频教程-Nodejs极速入门-Node.js
  18. windows打不开应用商店,edge浏览器不能登录同步
  19. 电容笔和触控笔有什么区别?第三方电容笔了解下
  20. 002概率论基本公式

热门文章

  1. c语言 博客园,C语言l|博客园作业10
  2. 使用springboot自带 MD5加密
  3. php 面向对象编程(class)之从入门到崩溃 基础篇
  4. 利用后中遍历结果,重构二叉树
  5. CentOS 7.2.5 安装 Redis 与 远程访问
  6. IDEA配置更加流畅 写代码起飞停不下来~
  7. python安装笔记_Python学习笔记(一)python的安装和配置
  8. bzoj1043 下落的圆盘
  9. from pristine store, because no checksum is recorded for this file
  10. 有效利用1 on 1