bzoj 2959 长跑(LCT+BCC+并查集)
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=2959
【题意】
n个点,提供操作:连边,修改点权,查询自定义边的方向后起点a终点b能经过的最大点权和。
【思路】
对于一个边的双连通分量,显然可以将权值全部获得。
如果没有连边操作,我们只需要将一个bcc缩点后求得a->b路径上的点权和即可。
加上连边后,使用并查集代表一个bcc,如果u,v之间不连通直接连边,如果已经连通则构成一个bcc,使用并查集将LCT的所有节点合并。
注意缩点后以并查集的代表元为该点,Access上找父亲的时候应该用父亲的bcc代表元。
【代码】
#include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
const int N = 3e5+; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct UFS {
int p[N];
int ifind(int x) {
if(p[x]==||x==p[x]) return p[x]=x;
return p[x]=ifind(p[x]);
}
void iunion(int x,int y) {
x=ifind(x),y=ifind(y);
if(x!=y) p[x]=y;
}
} bcc,S; namespace LCT { struct Node {
Node *ch[],*fa;
int v,rev,sum;
Node() {}
Node(int x) ;
void reverse() {
rev^=;
swap(ch[],ch[]);
}
void up_push() {
if(fa->ch[]==this||fa->ch[]==this)
fa->up_push();
if(rev) {
ch[]->reverse();
ch[]->reverse();
rev=;
}
}
void maintain() {
sum=v+ch[]->sum+ch[]->sum;
}
} T[N],*null=&T[];
Node::Node(int x) {
rev=;
v=sum=x;
ch[]=ch[]=fa=null;
} void rot(Node* o,int d) {
Node *p=o->fa;
p->ch[d]=o->ch[d^];
o->ch[d^]->fa=p;
o->ch[d^]=p;
o->fa=p->fa;
if(p==p->fa->ch[])
p->fa->ch[]=o;
else if(p==p->fa->ch[])
p->fa->ch[]=o;
p->fa=o;
p->maintain();
}
void splay(Node *o) {
o->up_push();
Node *nf,*nff;
while(o->fa->ch[]==o||o->fa->ch[]==o) {
nf=o->fa,nff=nf->fa;
if(o==nf->ch[]) {
if(nf==nff->ch[]) rot(nf,);
rot(o,);
} else {
if(nf==nff->ch[]) rot(nf,);
rot(o,);
}
}
o->maintain();
}
void Access(Node *o) {
Node *son=null;
while(o!=null) {
splay(o);
o->ch[]=son;
o->maintain();
o->fa=&T[bcc.ifind(o->fa-T)];
son=o; o=o->fa;
}
}
void evert(Node *o) {
Access(o);
splay(o);
o->reverse();
}
void Link(Node *u, Node *v) {
evert(u);
u->fa=v;
} } using namespace LCT; int n,m,a[N]; void merge(Node* &u,Node* v)
{
if(u==null) return ;
v->v+=u->v;
bcc.iunion(u-T,v-T);
merge(u->ch[],v);
merge(u->ch[],v);
u=null;
} int main()
{
n=read(),m=read();
FOR(i,,n) {
a[i]=read(); T[i]=Node(a[i]);
}
int op,u,v;
FOR(i,,m) {
op=read(),u=read(),v=read();
if(op==) {
u=bcc.ifind(u),v=bcc.ifind(v);
if(u==v) continue;
if(S.ifind(u)!=S.ifind(v))
Link(&T[u],&T[v]),
S.iunion(u,v);
else {
evert(&T[u]);
Access(&T[v]),splay(&T[v]);
merge(T[v].ch[],&T[v]);
merge(T[v].ch[],&T[v]);
T[v].maintain();
}
} else
if(op==) {
splay(&T[bcc.ifind(u)]);
T[bcc.ifind(u)].v+=v-a[u];
T[bcc.ifind(u)].maintain();
a[u]=v;
} else {
u=bcc.ifind(u),v=bcc.ifind(v);
if(S.ifind(u)!=S.ifind(v)) puts("-1");
else {
evert(&T[u]);
Access(&T[v]),splay(&T[v]);
printf("%d\n",T[v].sum);
}
}
}
return ;
}
Q:打码的最怕什么
A:手残和眼瞎。
真不巧,我两样都是
bzoj 2959 长跑(LCT+BCC+并查集)的更多相关文章
- BZOJ 2959 长跑 (LCT、并查集)
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2959 题解 真是被这题搞得心态大崩--调了7个小时--然而并查集都能写成\(O(n^2) ...
- BZOJ 2959: 长跑 lct 双联通分量 并查集 splay
http://www.lydsy.com/JudgeOnline/problem.php?id=2959 用两个并查集维护双联通分量的编号和合并. #include<iostream> # ...
- BZOJ 2959 长跑 (LCT+并查集)
题面:BZOJ传送门 当成有向边做的发现过不去样例,改成无向边就忘了原来的思路.. 因为成环的点一定都能取到,我们把它们压成一个新点,权值为环上所有点的权值和 这样保证了图是一颗森林 每次询问转化为, ...
- BZOJ 2959: 长跑 [lct 双连通分量 并查集]
2959: 长跑 题意:字词加入边,修改点权,询问两点间走一条路径的最大点权和.不一定是树 不是树
- BZOJ.2054.疯狂的馒头(并查集)
BZOJ 倒序处理,就是并查集傻题了.. 并查集就是确定下一个未染色位置的,直接跳到那个位置染.然而我越想越麻烦=-= 以为有线性的做法,发现还是要并查集.. 数据随机线段树也能过去. //18400 ...
- 2021.08.03 BZOJ 疯狂的馒头(并查集)
2021.08.03 BZOJ 疯狂的馒头(并查集) 疯狂的馒头 - 题目 - 黑暗爆炸OJ (darkbzoj.tk) 重点: 1.并查集的神奇运用 2.离线化 题意: 给一个长为n的序列,进行m次 ...
- bzoj 2959: 长跑【LCT+并查集】
如果没有环的话直接LCT 考虑有环怎么办,如果是静态的话就tarjan了,但是这里要动态的缩环 具体是link操作的时候看一下是否成环(两点已联通),成环的话就用并查集把这条链缩到一个点,把权值加给祖 ...
- BZOJ 2959: 长跑 解题报告
2959: 长跑 Description 某校开展了同学们喜闻乐见的阳光长跑活动.为了能"为祖国健康工作五十年",同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑 ...
- bzoj 2959: 长跑
Description 某校开展了同学们喜闻乐见的阳光长跑活动.为了能"为祖国健康工作五十年",同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑运动.一时间操场上 ...
随机推荐
- linux软中断与硬中断实现原理概述
linux软中断与硬中断实现原理概述. 1.软中断通过open_softirq注册一个软中断处理函数,即在软中断向量表softirq_vec数组中添加新的软中断处理action函数. 2.调用rais ...
- s3cmd的安装与使用
s3cmd 是一款 Amazon S3 命令行工具.它不仅能上传.下载.同步,还能设置权限,下面是完整的安装使用指南. 主要是还是用来储存日志文件或者其他什么资料. https://wangyan. ...
- Delphi 7事件的多处理机制
Delphi 7事件的多处理机制Allen Tao2007-08-19 首先解释一下这个题目.在我使用Delphi 7的过程中发现,一个对象的事件只能被一个过程处理.如果多次给这个对象的事件赋给处理事 ...
- mac root用户初始密码设置
具体方法如下: 1)sudo su切换到root,输入的用户密码是当前用户的密码: 2)切换到root后,执行passwd root,设置root用户密码即可.
- [前端]利用a标签获取url里所需的内容
function parseURL(url) { var a = document.createElement('a'); a.href = url; return { source: url, pr ...
- JVM学习笔记(二)------Java代码编译和执行的整个过程
Java代码编译是由Java源码编译器来完成,流程图如下所示: Java字节码的执行是由JVM执行引擎来完成,流程图如下所示: Java代码编译和执行的整个过程包含了以下三个重要的机制: Java源码 ...
- 注意:C++中double的表示是有误差的
注意:C++中double的表示是有误差的,直接通过下面的例子看一下 #include<iostream> using namespace std; int main() { double ...
- devDependencies和dependencies的区别
我们在使用npm install 安装模块或插件的时候,有两种命令把他们写入到 package.json 文件里面去,比如: --save-dev --save 在 package.json 文件里面 ...
- poj 1151 Atlantis (离散化 + 扫描线 + 线段树 矩形面积并)
题目链接题意:给定n个矩形,求面积并,分别给矩形左上角的坐标和右上角的坐标. 分析: 映射到y轴,并且记录下每个的y坐标,并对y坐标进行离散. 然后按照x从左向右扫描. #include <io ...
- 宏os_file_read_func
# define os_file_read(file, buf, offset, offset_high, n) \ os_file_read_func(file, buf, offset, offs ...