【题目链接】

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+并查集)的更多相关文章

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

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

  2. BZOJ 2959: 长跑 lct 双联通分量 并查集 splay

    http://www.lydsy.com/JudgeOnline/problem.php?id=2959 用两个并查集维护双联通分量的编号和合并. #include<iostream> # ...

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

    题面:BZOJ传送门 当成有向边做的发现过不去样例,改成无向边就忘了原来的思路.. 因为成环的点一定都能取到,我们把它们压成一个新点,权值为环上所有点的权值和 这样保证了图是一颗森林 每次询问转化为, ...

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

    2959: 长跑 题意:字词加入边,修改点权,询问两点间走一条路径的最大点权和.不一定是树 不是树

  5. BZOJ.2054.疯狂的馒头(并查集)

    BZOJ 倒序处理,就是并查集傻题了.. 并查集就是确定下一个未染色位置的,直接跳到那个位置染.然而我越想越麻烦=-= 以为有线性的做法,发现还是要并查集.. 数据随机线段树也能过去. //18400 ...

  6. 2021.08.03 BZOJ 疯狂的馒头(并查集)

    2021.08.03 BZOJ 疯狂的馒头(并查集) 疯狂的馒头 - 题目 - 黑暗爆炸OJ (darkbzoj.tk) 重点: 1.并查集的神奇运用 2.离线化 题意: 给一个长为n的序列,进行m次 ...

  7. bzoj 2959: 长跑【LCT+并查集】

    如果没有环的话直接LCT 考虑有环怎么办,如果是静态的话就tarjan了,但是这里要动态的缩环 具体是link操作的时候看一下是否成环(两点已联通),成环的话就用并查集把这条链缩到一个点,把权值加给祖 ...

  8. BZOJ 2959: 长跑 解题报告

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

  9. bzoj 2959: 长跑

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

随机推荐

  1. java中什么时候该用static修饰方法?有什么好处或者坏处?

    当一个方法或者变量需要初始化加载,或者是经常被调用的时候可以加上static.用static修饰的方法可以用类名直接调用,不用的一定要先实例化一个对象然后才可以调用比如 person这个类里面有一个方 ...

  2. 开发版本控制git

    git init 在git命令行中依次输入 touch readme.txt并回车, git add . 点代表所有, git commit -m "init first"并回车, ...

  3. eclipse怎么集成配置JDK和Tomcat

    eclipse怎么集成配置JDK和Tomcat_电脑软件_百度经验http://jingyan.baidu.com/album/db55b609ab6a1f4ba30a2f2c.html?picind ...

  4. 88. Merge Sorted Array

    题目: Given two sorted integer arrays A and B, merge B into A as one sorted array. Note:You may assume ...

  5. linux自动启动shell和init概述(fedora use systemmd now!!!)

    linux运行级别  linux启动之后会在一个级别运行,下面列出了这些运行级别: 0 系统停止 1 单用户系统,不需要登陆 2 多用户系统但不支持NFS,命令行模式登陆 3 完整多用户模式,命令行模 ...

  6. .Net MVC API初试

    新建.net mvc api项目后,直接运行,默认会访问http://localhost:xxxx/Home/Index页面,这个页面不是要访问的API页面. 从项目的目录可以看出,默认的API页面访 ...

  7. 解决PHP开启gd库无效的问题

    最近需要重新安装PHP,以前一直使用的都是XAMPP,基本上都不需要自己配置,现在准备直接下载官方原版的Apache和PHP,自己来慢慢摸索如何继承配置. 我下载的Apache版本为2.2.25,PH ...

  8. Android权限安全(7)binder,service,zygote安全相关简介

    binder 提供服务的service中的binder thread 检查调用者的uid 不是root,system就异常. service 也检查调用者的uid 不是root,system,只能注册 ...

  9. Android app Splash页的替代方案

    一般的App想要显示公司的log什么的,都会在启动的第一个页面显示,就是SplashActivity. 目前在看到一个替代SplashActivity的方案. 使用SplashActivity的时候, ...

  10. 国内顺利使用Google的另类技巧

    在特殊的地方和特殊的时间,流畅顺利使用Google的方法也会变得很特殊.本文不定期保持维护更新,删除不能用的,增加新的网址. 分享一些奇葩的Google使用方法,通过下列网址也可以使用Google来搜 ...